/*
 * This software is Copyright (c) 2016, Dhiru Kholia <dhiru.kholia at gmail.com>,
 * and it is hereby released to the general public under the following terms:
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted.
 */

#if FMT_EXTERNS_H
extern struct fmt_main fmt_pfx_ng;
#elif FMT_REGISTERS_H
john_register_one(&fmt_pfx_ng);
#else

#include <string.h>
#include "arch.h"
#include "misc.h"
#include "memory.h"
#include "common.h"
#include "formats.h"
#include "johnswap.h"
#include "hmac_sha.h"
#ifdef _OPENMP
#include <omp.h>
#ifndef OMP_SCALE
#define OMP_SCALE               1
#endif
#endif
#include "twofish.h"
#include "sha.h"
#include "loader.h"
#include "simd-intrinsics.h"
#include "pkcs12.h"
#include "memdbg.h"

#define FORMAT_LABEL            "pfx-ng"
#define FORMAT_NAME             ""
#define ALGORITHM_NAME          "PKCS12 PBE (.pfx, .p12) (SHA-1 to SHA-512) " SHA1_ALGORITHM_NAME
// I could not get openssl to use passwords > 48 bytes, so we will cut support at this length.
#define PLAINTEXT_LENGTH        48
#define SALT_SIZE               sizeof(struct custom_salt)
#define SALT_ALIGN              sizeof(ARCH_WORD_32)
#define BINARY_SIZE             20
#define BINARY_ALIGN            sizeof(ARCH_WORD_32)
#define BENCHMARK_COMMENT       ""
#define BENCHMARK_LENGTH        -1
#if !defined(SIMD_COEF_32)
#define MIN_KEYS_PER_CRYPT	1
#define MAX_KEYS_PER_CRYPT	1
#else
// FIXME.  We have to handle this in some other manner (in init).  We need to
// find the LCM of all possible 'groups'.  So if we have 2 8 and 24 as our
// groups, this count needs to be 24.  If it was 2 8 24 and 32, then we would
// need min/max keys to be 96
#define MIN_KEYS_PER_CRYPT	SSE_GROUP_SZ_SHA1
#define MAX_KEYS_PER_CRYPT	SSE_GROUP_SZ_SHA1
#endif
#define FORMAT_TAG              "$pfxng$"
#define FORMAT_TAG_LENGTH       (sizeof(FORMAT_TAG) - 1)

#define MAX_DATA_LENGTH         8192 // XXX ensure this is large enough

static struct fmt_tests tests[] = {
	{"$pfxng$1$20$2048$8$e861d3357729c35f$308206513082032f06092a864886f70d010706a08203203082031c0201003082031506092a864886f70d010701301c060a2a864886f70d010c0103300e04086c933ea5111fd24602020800808202e83c56ad18c45e54aaca4d170750cfbfb3059d6cf161e49d379eab15e722216cb479eee8da7b6e6ffc89e01fbf30f4eb5e1b88ca146c166c700a68473d25a0979344cc60d1e58230a12d24b8be6e9174d3afecdf111cd7d96527831ac9c8f4bf3817cda021f34b61899f2a75fe511e8dedfb70367fa9902d2d3e500f853cc5a99ec8672a44713d24ae49382a20db6349bc48b23ad8d4be3aa31ba7e6d720590b5e4f6b0b5d84b7789ae9da7a80bfa3c27e507fc87e7bc943cff967db6b76f904ac52c1db5cfe9915fa3493cd42b8db6deae62bc01593e34bc8598f27a24cdfd242701ff72d997f959f3a933ab5a2762df33849c116715b78cb0d83267aff913619cbbdf003e13318e4b188a8a4f851b9f59ae2c71ab215c565f7872e5d54c06f92d6f59eaf19d95f9b4526d52d289cd17bc0c2079f9f13c20a70a566773d90ca6d888386d909b6362cb79e15cf547dceab1fe793c577b70f72463969f7b416fb5a6228053363558df18588b53406343ab320a1bbf1757b67ef8e3075f44dee4521f4a461d37ea894c940bc87f9bd33276f2843ff5922fd8e61d22a8619ad23154880fd7d957c0f151458fc4f686d96695a823b08c1795daaf79e41118a3c57ee065a693853a9c4b2004440662f51d63bb9973dc4bb8c541d424416c57d01a825be4d31dab7c7f4b2b738e4bbfdda1e3d3b95e026dadee4dfe155c0f4a24991693f679b452516bc19eab7cf7eb41b476358583d46630e8cda55974b8fcbe25b93e91e73f584a913149137c1c20d13f38826d8dba9bcf5504b8cee77e20a19d6fb050e9213b8aeb11c26a871c600701aea352ba2dcea15d8010d25034f64aa488b580b8282d226f8203bba6aa424b0a25bcceb9c7c718b6c276022d988ca063d2e88350d68903f95aa3265b44d909c07fa9477a5dfcfe3b5ed49b789d6e1c13aca012630343021dbc0c0f17dae6688eae495b76d21be49ced2c2e98e1068d8725d8a581958fb2530871dff1b3f910ae8beb3bc07bfb4b1d2d73fc5d440dc9bcd32ba656c32e357051bef3082031a06092a864886f70d010701a082030b0482030730820303308202ff060b2a864886f70d010c0a0102a08202a6308202a2301c060a2a864886f70d010c0103300e0408749558ace83617660202080004820280ef790b9cd427ec99a350a6e3afb1727cf3dd859d5377897805a7093e1ca42ab8cccc6c52d2b86d61ed55b5bd743fb2a4ec556b438933a9d97a55e5ad1fb3f9967e550be3d708feb5c7287e31afed165a4a91bd5a80292a1e061f97a8c11339963843348badf3fd898e89fd92bda5ad0195d8d4f75e7bce9f0518eeb85365860cd32ad5cea0958efef02bfb74aec0af0765729dae079f5eb08b099d3b06a9b9c6cd6f1e1e4170208ebec3c61ae3421e90cef0f2b5cd2187e43cc4ceecf4aec06340f886efb94f517e578d13659392246a69505de3914b719fba74709ef0f03f010429f899dbddab950f6e58462b2fe2663986a5e0c8ff235e89bca3bb6e41fcd602a0277a83822ac1a14101c83fd1cafdc45c1980ecf54ef092deb2fea736b428158e0847256fc1211f94ea8075145be5a5fb26206e125d55f45500844f1a83f063d0be19b60427dadbd89109bb9ee31a1ac79c863204e8e80c044b8b6bc45c756c26be514e4270a293faf4608065a27b4a51253cb9f831614d5c7f25ec1d4e36063e68e4e405c1f4deb98a786c57a376609441f2dcbe6393487b884624570f6cbb02b53f58ea4acb0faedd2931293dc87664a0c589322480686f6613ffb794c3b3b1872cd7a418712a35666b53bd8383f2e7aa6e8a9e20dd3d46cc3aaaaf17841732dde708ba5611ebcc8777fb3f7b65f2cf95992fdf4f5a17ddf01f3ebe5fb6c9cd58cb74553865cbec3c9d391dcc3e96e654faf7be7fdc8d5fb5dff98799e740147d2ca4b6df47560a4a20bd8f30cf5b495f4e919c9efad3aa59491a3e2ba4e53606e2016ce13e8271e70ccd5b57eec99a8604caf5997e648f3eb541769267f9cdf76aa84917ebd8a1f60a973ed22cca9fa0d3589bb77dafed82ea4f8cd19d3146301f06092a864886f70d01091431121e10006f00700065006e00770061006c006c302306092a864886f70d01091531160414a38a6be4b090be5e29259879b75e0e482f4a4dd8$a790274918578289d80aa9fd0d526923f7b8f4d4", "openwall"},
	{"$pfxng$1$20$1024$20$456a2344e138862de7ad2e0b274952ef566e2b63$308209cb3082057806092a864886f70d010701a082056904820565308205613082055d060b2a864886f70d010c0a0102a08204fa308204f63028060a2a864886f70d010c0103301a0414e9a49f4190a3084e02ceba2f049303750f6646da02020400048204c8cd40bb89c287b9fe70a88825e33a648c76aa1b35d93131d445e48943ee50ff8a0aee6a0483a289fbacf21290a8553e3414ea6bd6b305407d709bbaf915a99430c998d9ba68e71f4036d42feb386061d645433390658df91bd4e9750a39f9288f7cf8001e2adc8e4d7480f1a5e2d63799df20d9eb956f86b33330ec2c206b1ae47cf54d9cf2cdd970664c251e64cc725456e2c14506cfd7d9ff1d2894a50093fff4f29d5967a0f788ed707ade93cb3ad7e87d96dad844d2037f4d5e863ec5170c0f1d4514d752a266cd4db49b63c5d86646e54a68187ddc99b00499286f79e2e7c54e30d3a1b1f035d7113180d072c7218d399f8b5427dc2d6fcb42518bd6bb97f74c97ea2358ef39fb176397fe7729cd5c3a474423f0a0e74a91c77bb27b24f82463081fed53bdf216840b2c60482846010b654e2c74db4abfb07936e0cc9d0d133ac7a4baa03091de25f6eea70d85fe9376349731ecc03fe437175101fd6698929f43a94835c6453b68335f478cfa1fab1ddf0236570ca5a07cebf1aa3c36d7804654a5eac8328377abba3b81627fcac7f1dbdb56ba1f0f861af9967c5d245459a81891fb5dd833f0bca633eb616cf10397b295d857c63501e85fb9f11f1fd3dd80baac425ecf0efa012817ca9b23e06575a3942613fad67b4bda4fabfd29bd1897b0623d6d47ec000bd656f5b7c78b9a4808ac022524b17a8df676b86dc29b6d008d09cb1148110bd07464c071504d7dae5803602247da1e4cd5d490771322d7eb568d0ad0293f4d2626ac0f60f568a92eccd097f6d5247e043b7cdb52ddfef0516e7053fb42b7d1b16564f1c862c1bf45436290a5dab1f0e90b24bdd4433ce0cbcc7b0eafc445dcc6fe8a52e606d3977ce6d9e44f037ea8dbf36bce63a877aaafde13b1bb5005856d315f30fd4feaf26ef8eeef899802aa2442364c147b074c64878a696a1f2cadd9bacb187b62c239c16f163d6c44e157dd8daa4610142eb40dadbc3405c4ade7d127db20bc4384bd1d4c2a2a5dc907aa0468c2485654bceeee3d4011d74e6e85ed88811ccf1cd6b3d5540c5709b8e14fb9e610b552502343ec739e8c9c6d6459062f76275de1fa1b24ed8a9924ea9176dfb89520b7fbec9e9968bd0320afc513e560966b524a82ef5a206f1823742e820bbbe6dca6b0a33c8f04208376bfd01f049f666c735b1efe2550a8601b1839bf045c56a9772a3e25235d2fb61f9007713ff57ae47f6335a44e6730bdaaebe833996aaaa78138ddb7d8719570a429debb8183fbd07f71a037335ec5b1d40c62f7163b85dc71d8db536c9092f155429b65ea81f8ff3c7892ebf881c107ea2c167df47d044ae7ed3fb5328d673753450c82d7049dfeaf1dde821a0ee0d6676a1656584cdbd4532f8d2493ea4794d88acacb147f19ca15777a67fe5031991ebc45ea43e87574f9d2f52de0722d6cc7f5b7a378a461148f1f7c5ee8bc7c7ae4fe80b4eed13b35d16906a084120c645812db0bd70e419c004512f284ab7635f17ee2ecc728aef2cda256b86fb4cc9d3e21736249735962d6ccd307a67fdbdb0815184f116eb1747de19449c6fb9410cb669fa2a3f2ab5ca16c3cca918555b583f61f2126aa0895ccdac7a5604ca1e84a76c15c508d620bb9037e5e5acf97e94438a059bc771d84dc1f63fd3f4780274a2f0a03f9b09a0cf4638e0c317f6ebb24f9062fe8c7023d4c06f3c67c9ac2008e8da33150302b06092a864886f70d010914311e1e1c006d0079005f00630065007200740069006600690063006100740065302106092a864886f70d0109153114041254696d6520313334303937373036353139303082044b06092a864886f70d010706a082043c308204380201003082043106092a864886f70d0107013028060a2a864886f70d010c0106301a04147d79e2d2b2986ea4d929b3ba8b956739a393b00802020400808203f82c0ebc2a236e5ffc4dff9e02344449f642fdf3b16da9b2e56d5a5e35f323b23b8ff915fbaf2ff70705465170ccd259a70bb1cde9f76e593f9a7a0d4764806dad2fa5c3b1ee2711e9dbbcaa874f8985f1b6c2ca1d55c919cf9e88aababe7826107cdb937e7cca57809b20a6351504ab688327e4df957a3c167772cf66aed6a2007ead81896465d4931efe7c3291a49761f1428c766fd82e1736218e90d9f8592475d164d9a79f3424cb6a543f7040d3f0dba6996d496f4f603b7d59527e5c9c89b3f96c55fa73b72385629cbd606cf9f88833db66bb1519dee62a0cd4989d93457fa1162b594b86bc7134c9aa530fe10d62b914f1818395f82d5224c3bc793a04b0ab41dc98694535f5bfbf2aa943d6c794f407e02248be842c55789091d1cc28bbfdf86bc1346142b057558ce1e64e38f8b2d7d68d539150f3de23f43d59637ae678f3687e69b52fdf46f54c32b84a658a2a69fb16da7ebb45ea84c9e38d6cedfc1227b86a6ea3094d0908d588213834192849fa5c25b2460bb22fdd9d9e317efaca646ea582ecb50f6a466f55ae38573afe904eadf42b6c596c8740dbf92cbd38c347624f3399ac2d20d0727f897f38417901dfdaa798631af8992fcad5d708882576036531d2deb867fe46d63921dc50b8c73fbc59586a861d7ae47c2a5ff892e9dffc6d8e6e8161506819ebc020cfb7bc4c1708832d53f8cc864012ab8379a1323e23b0edb5ffe48a942411cef6197f5545ae6822a3096db972f96d4d200ba600a1e95595d4532e7a9861b233f71ff37ea3c19143c87dd6d4a3f3186a7693dc11067c7b4c967984d4bbbf9d88acacb1ff3ba4536ea265a0503865d86af408748fe8191119cd7b570b5352f190265d5d468e911ba0020b526d3892119fda21243568cfa638251c9044c91a88d2f8a05dd0d90088b0b79ac2a2ca263aa108160a7f6943ce709a02743afb6e4ec9a7f7535635f839c2baf938418accec3d5c1ad2bbcec69ab337155bd0bb1b45c7e16e32f251d4da7796f013d6d502581853da6ab9736382115141886c14512fb5ca22e3e9e20366257579eb4225a6a3716457b9b1c0df63cb71a34b888de021f3520d62e96675ea8767e23d55b50e9aa40babafe398f5482c83f8caa57d7ed3486ce7dedace7158067194892defe38af28c1695cd6f14a1ddae959541fab3b59e72c17d2a67d980c749ef00b1f61ece68d81c79b4ec4f4d9eeaad43895a0dc9d86f4d7fe114f01189b3db72ee92963d4403c3aca8bf6d60ef7ee7fcd8102b3247048b4d517cd0ab76a0f8d68d33733934cb35a8e40d7de70c4f166c453fda74553069c51dd33f6f513bb9ef0a983187fc7d896c668590577a4e269688cc7b9fbd1f3fe77d3f431cf002043c43e1cae82b22018931f1337ee276d49c19163a866ef10a64ac5b013db1cb1c$501f5cd8e454e44b6925715c4d2605a8d4ce70d0", "my_password"},
	{"$pfxng$1$20$2048$8$c70bc3c11be46232$308205f9308202cf06092a864886f70d010706a08202c0308202bc020100308202b506092a864886f70d010701301c060a2a864886f70d010c0103300e0408aeab408a953dae400202080080820288eac5f49ac4a3c50ec87cfd7592cd19e7deafbd62f58eb68ec542bf073778bf238533fc1363ff41e87dc72e75d97fbbd9707ca0fa171216f5c5d56906efc96f15883138b31a151b40ae2d72e7d4310095f03c85d75672d983566db3cae50c59613a26b64d54fcaa5cd8c328854359868eae40e66c7f527ce213d3a8645d012afa3fbb9ddab6c6dd1bc3863cc2c0014380e606da2f7f7ede8ef1c8a35d48b4f150651387461cf1327f12629411b3b3f7b0d8e3dce9e03b5ef52b1cb911b469685b491ceec0276a6c3a2e64beab805fa67cea73c0ed6bd498d563a89b874032fed141857f0a80342442d20af18a084877df28b3abd4c9d7218551bef523c17b4729d0689b0833e190e3e60995ca3fe5075629ea4ffde3e65f20777086d5cbcfe742cc22ef46d06e9ba35e4017eb35fec30cb7ddc37fa22daa9e77e202d864f6d34541d854f00f9e8c1445ac432bff67a5a00b6cd0da5eb796c7a44e92b5c67f55de92ebcef8f690d7b3892362d884f2d8c657db5dc308c95a43cc42bfc5449b45c05e9e60ca5d88d0c07b9cbe6b76da91f7c572e1c02ef71a18833e6779df711a4104e21d5939a982e19e22292df280adc3f0b10339f53fdbc44356a95c27eb23932302678b86094d5f4d60e028af61c01d7fcd83ab9f78c4499c3e7bd29507c397ca43d397b90cb267a6ec15f37b50cf4f2d82d4a4fe8f56355c27c20cfd93ed5f84f321244c7a7dc404619b3f9bb83affbf4d1d702b336ac3e504ccb86c18a979354faf0bf4e725fe1ef051dca8ce0209b7905f8f19c5ec51fbede48f57cbb90d14d666ca09fb4d0b92c6e2a54e8ad1b51cc20cbe17c86901f76d509bcbf0d6ecbf08685da20ec75c11d8c509cf2ab9842e2be34aa24920d4a035e1641cf3d5b1669d46ac9531514d3082032206092a864886f70d010701a08203130482030f3082030b30820307060b2a864886f70d010c0a0102a08202a6308202a2301c060a2a864886f70d010c0103300e040806de2bcadc588fa502020800048202800d03f420c35a4b8e1b3b0592306996feb16d41001d0aace08d4dadc51fb2498f504c4bf57a54eec39102d76665eed9c46006c9a181bca37c64e96f11b0c7c24bea8bdcdab174ec1aa2f85b6a0ae4ba082516e977a212ee8ecb5d79b7431f951749046ffad4fbb2106016cb024da53894b7f2c7e0b8d2af6a4823d57d30b884fba32bebb88c0bf53f370663f37a4276750ee22c2a76fb428f888dbc1bba10bc0976c7a5e73181dd84aaccfe98e2fee04212f1dea2284bbd0fb990646fb276610198eaf210d44c63d245234fd6c7486d2b899395d75ca569f4cc7f1c1b9583d2e5a3310ffd7826fcf206cca0fd2557b9317ef638e5d553ffff917e41c6a3f184ca72a1581725a954f5ed157dc9b04b1f2f044bc267f9de7e4d80aef84b91a94b66dacf86ab78928c873b2b8963ef1b2fac24a603011edb223aa8aa22bf3784e6938edf7811516ae4862a77693b1c254a4ed30dc85bf4b5a79942f841dc09db799eaa89051fc51eb917d9faa9781af961ec34e2df5ba531628d777437b282a2548d9f64eb72069f0325cbc65123c67606c0812920862480457d0df6ea547a9f778d48b24b6ca72d47bfd4cc6431e126a43c8d14ecae263da06bcb73413091d154c0e67fb6f629131c2d4a0d1b750941b0ab8a188ddb4cd427396d83f922bee0f3a85383d5bcb8ec89338b933d181aba79d7f2566e74b9a01ecd755ca4ab38963fcf36c985f5513ea678a822cf8acab673234bcc3d7b210da1b762814a0cf658e5d8ec9305b887d444131278f790fb8c77f3737c5f8f864ac7554bbf4ee8c3d78523462628faac312e2d37062c72d05ba2fed1a51c9017a75160cd267897802463e638a8e02c2a2230f518365470aca7e8c418bfe99227ad13f0bf2bf6d4124724af314e302306092a864886f70d0109153116041467a3f379b2dd87441f6abf68c9a9f8429a92c044302706092a864886f70d010914311a1e1800740065007300740069006e006700310032003300340035$585f5cfb43702b6d02b55418ce3925d04cdbcc63", "testing12345"},
	{"$pfxng$256$32$2048$8$eda9c105494d9435$308205eb308202c706092a864886f70d010706a08202b8308202b4020100308202ad06092a864886f70d010701301c060a2a864886f70d010c0103300e04081e887b937597d33f02020800808202805b10b55d2c64713d8085b1b3633dcf1c87b8a20fa9a3c2728dd7ba8dcbe084539bca898b4c884e3a7ff15458b155c50e7a5ac6639c300b8234e4424819e167283160286d53f8ff9c78e05eeb250e16a7445e24ba87f0e3a111ee3803d56c038372fdf96311849b7a35513ab497be68edf0e306ae91b3a8790a0a6043e4051b4b2b90d9c2ca1b5d51fda2bbc6aa136576e7db2362af99c7be31947ac1ba4dade30c8a4c5dc9ae517528ae7d7e34e25ce2f7f3a42c9f0bf6ccf71d84a1117b6acfc95c3493f1937d42c019c7385b86028cd1795e5d991e208aa54d56499c3fe5b29ffe97f8194fed46062d89127553de7f73717435e6c27db8c9cb6a8f06083e9d17c00f5afc54c2d6c71d7f4c9b8747bb53539c40a5d3cc50c1c21eb30a28dad407cc31438337153db91c6b9dcabfbba121d976e9deb182b530e94b63799901f02642973e3ee41905f9cbbbcdecdc18bb4a7e5cd540031cdaca594602ef172c91ac4cee0c2e86cb34b177180e05171e22557201ad9376f5fe99119128dc32e1ceb728e8ef1a372c5bf2649ba379bb9ba300d6e9e3c7a37f5c02280489083b729c6beaa85aae2cab3b05c8543626118aa3ac42f09fac3b26898ac9762ed88ab4099aac653c2d54fa967179893408cd5b61e2ceda8e6f7789752d78357f1f9762afb621d2444b2e8ae5a09596d37ed8309276ffded09434616e88fe075d2c3d983f46b0e1b4f330fe2939bb9985ab8becefabb3929096c18ca8ab76d65eb7642454264c8617f11d3211a24b68a5cd146e88581567681f5db43d46dee2d3c3f0ae1dd6f194691331fd6166bc4ee9d076e571a30df4015037c7c831e5b837896d5132fdeaa4cbff9fa372f873cfd3e5a9037cc3b95d2b0d5fd2a07691b1fc27f604653082031c06092a864886f70d010701a082030d048203093082030530820301060b2a864886f70d010c0a0102a08202a6308202a2301c060a2a864886f70d010c0103300e0408751fbd442d0cf3ff0202080004820280fc073ddf174703f1be2d4e2927ef21318267a66f2d1c650ed82123a210f14ad8b8cc4f5dbdae189659fec6748f8b12977dbf586f313282ef3884a2eae3fe6df56a4b335c647764ede9160063baf0614d153ce5356fcb0c41ac97eaa30d49c5156064f56a481dddab298feaa96db78263251295013ac8c63a0958c60fff45301571598659ad292f3c85691696350a3d4c3661cfed45ae243c51e333872de4535ca30819b9b71cb70adb05853757ef3c26613ab622fa828e69ba99859b5272c853afaae61ca7787bb5a629ac7f4fb7d75a854545a559dc06743c7722e848dafe57bde7d2179453f618cbe194cef4a1a173656c765277ea0406ea030efc857668a11a62ae61f3972b46f324b46cb29f8b5bd7b54ee1dfbf3c87ebf1732af3c6304a3b6a3fbb8270ef8c3a8558c942fe018f94e0127cbd1e36fe346f46fdc68a9634ee3afdbd811254377b3e8f71c43c4f5e69bc3655ce8c8710da0ef576c2f6c00b649d32976eb5562b2c7df0c646a36f11b86946accd9bd018e81d5dc7369bdfc1ce8da7fdf39a5fa9732963c0cf81da9d0eeb476e824706151513d3f7b5b606085b900fec3a1e0fe673ed413ac6713c81db5db7080d8c3dbb426299841feb3fd58195218d01f598e2d4ac41376adc768c3f68110f1453bb30b293d98e980ecb325fbb3f87dce6e897f407a2b32c49e2329338ffe327d1c3fb28427af1c9dee4f7e5714ce6355357f8c9634c24922a70b0b7c7fa8ddc9bd55de97c768def9b04e694aa26a5f4f4f121fa24ee62baec2a1a70db99efda22c6975e11ecd9138747e6366ebaafa9abd02c61bb2b0189de5c315095bf371a397c654f0b0a8e4fec15e01bbaccd3fef22d6359270098af58e6c2f203c992fc093b08f932220d769700593148302106092a864886f70d01091431141e12007400650073007400310032003300340035302306092a864886f70d01091531160414ca1ff7ddc2ec65acd899d4ccabf13d4b72def78a$c47c2a58c174a8a3540d6103de3403d93b9c66b6769e74022b52981ff4ae529a", "test12345"},
	{"$pfxng$512$64$2048$8$d76feff5e054a36e$308205f9308202cf06092a864886f70d010706a08202c0308202bc020100308202b506092a864886f70d010701301c060a2a864886f70d010c0103300e04083babd1a7ed8725b802020800808202885a0ce329788b3c935db5ac040239817531e749b8e2e7eafe53c45e464cfbe27c6b2235fe934e8be0464dd0c8861b31a8781c74704f2c5c109771b7a3ac14c978d94a53115546df674e202cc4b051d2e094ee59afe3c81b20c0c9ca5c6fa0b51024919844b7c94aa61f4c7ed4bd238447f82657b9bdbb3925552c6692532fbc7ff775b71796118f7c5d6c243ae5b0f7d4587d9c079498be2b41105dca2a4375e5651dc1d3dd5a003a62a9669f3931221e71e2a1e9387dd35d866b3a81513be6134a4e192593447b6965d40e276853bed834e04d6aa68139e29a8c4981665cef6a1b3690f81add179a84f5bd5620093a36270dc3c4594d4e167b21b183ae5bac73484e7f2204288ec80521a0044730120b04334af45f391de13f8b29b9a2be2c9d7d252229d0e0ba3186f34b645b392efafe60c9a3a34b7f30e5fbf7078bcec794418ea2ec184699bae59f55734c47738b448b99d7f69815792642786e775491603ed921e45386892e182e5978fac39c37ca4953553a17dd549a065e7596720ebe6e01a87cea0b53210c540483a95bd08a8bd713667e27e37e54ad5bcbea66642e252c1f400ea8a1cb08907e80420b3778a56b55c154e420ad480dfb94fcbcb79a4f3b06f1cb41840de6d6a2f60513b69a5477bcc83f8b771fd40390b622ca1bb21d07df796360e72b2623f8628e45299ff45331a9ba80583665610ad82bd658e7e316f56f810751d95fbb574ed6d97dc65670fd076cd2092c63ceed5cb800c131a0971a74fef025cd3c3aa7a5aadd7724c2f84c879a26b40b7e5c6f0513c01cfb4a5bfea4132d7b25554d1a60e2cf73c96c9f10dce8014652f141e421dfe5e5386cbb0a6d22002bd86ac42ca542893973b497a431ba48d9bf5cbfe39ad0b980a4538e5cb15cf166643082032206092a864886f70d010701a08203130482030f3082030b30820307060b2a864886f70d010c0a0102a08202a6308202a2301c060a2a864886f70d010c0103300e0408c2fe6c7c551da0b802020800048202807903390797cba159723105cb53d25d5b1867c496d6005cf5370338c68d6078e105dff9f479f6402a7d1fb1c6c7ee7c5954990a6d83f5fee29cdf6f4bcb26b0ec09bb764bf3ddf2545e6569ade3fddb0f771cd832035c9ac3b4154af8f320e726907259c7a43fe1170e9244d2c314c055083da11860e1fc692fcd0144e6a38d3933e2801151e2cd4cb58211f4622dd8248c895823480ee77457e3ac86b23532e4e18a8f144a7906e80dacd3c2f4faea0df51e6e4f8175e45254e03996aa9838ad1b0e1537509416d75ab767e1f1d899afaf517219cce58bcce261da621863eef0a9ffb3e338760f76ffe46e48a6a4e911e85a1097023c6271f2c75b319c66c769ff16a75a0cc4bb542c74ad464eefd60d09ef83e390cefa532bf1104ecb5867a7e7e84feae114e0558425d3cd570f15447f461459ffdf1b1cce6efbb18abb734752066146f5aee630dca8ee8b77f6dbc9deb93282d7e6d559f3237bea628c440cb62bb950cf016b83c4160e386e5637cf35a15b695fc82ef4d86e5d559eff5572cb6c3f7cce02a256f96127333276199be9d187c8ebacbc2a284a365835c326aa38bdec0d0db2ca0cc8f576be802d4cc965d92a3fbf30179bbdfa913e6045ab3fdca5673cf899be130556d10cf6f6d0add3a5b622485e33cd765b95d94ee8f9a5146e6a9ed673d78c0c3ea2dbfca673fd3fbe9603ccc3f75788ab3ae6bbaa5fe547b2995d3593b30cd0efb0936e0cd5e525b539238edbaf7c0c0594f7f012581328fcd655d0710af1b83e4997535f9e99e9daf15fa51e521106de1a7757bf29c5af920fadd4540bedc06d6c123b5d9a99403ca7b4f4b7d422978055faa6aa7d046ebbe7653b8636ef13bb7a4c5909e52a238897a84af13d1393cf5a44b8b4b6c2314e302306092a864886f70d01091531160414ca1ff7ddc2ec65acd899d4ccabf13d4b72def78a302706092a864886f70d010914311a1e18007400650073007400310032003300340035003600370038$41fa1aff8851060cb5db172fc5b2143ae9a524148582d381599aabd96582ea1be2a6054dcf4e1a5c27566e7305a7b9a2a94ea83153f32c7c78efd57649812303", "test12345678"},
	{"$pfxng$224$28$2048$8$8ebbd2cf95ff5f8d$308209683082041f06092a864886f70d010706a08204103082040c0201003082040506092a864886f70d010701301c060a2a864886f70d010c0106300e040834ecec80694e37f602020800808203d8ec3f3a3fc8197e554166da292ca155e004828b46083a2f0a242f892f587a78db4165097c79ad56534887fffefdd1e35eeb7f129e6974b6643fa9fcd6d6e3228f4b37e1da371b23300d5cfb868114c1e1c61118188c32e3679ee23d9bcf0adce8699e3d7fdc36707a66efe61ecfada1117b4bf3f711a6e9eab20f90882d1c4f0928fc753a44f822c6c47f3c7896dc26fba03341d8b902fb00b669c661fd4982888f264d50ceec719aa14acd8393720a9127f3f44a93354e5c8477c6cca92e7755dd01d3d6bbca09bb549e3375c6467202bd2012ead920ba47df4851156f629fbbd2530e89738854e2ee2dcc49485bc930ac43156ca5f4e09a576bccef73095f8eefe811a71ae95d745c1d7592f0f1e22da89852df0dbcd30d42c3622df9f6149dcb76523a339072c07b10a1922e66d2d98e3991c2053b2f8377be7bda18dfc9205cbf37b37c370827941a038a34fd202a7e779a482cafe76de3e09e8d104240e05c3cc87a71f5527641b3d889ba9b685df949c0fb764713fdcb4d925dd86939dab3237cada323feb6cac95e4b7e68aec25cba82e3b458fbbeefd0a48830137bf962a451fc451e980e6d965bb5c2be4d6e38460340d6808149fe0fc114d83baab0f52cf4784c0dc98d9f93ce57a5f99a5119b9eafda12f520d130d9400e5fb317edb0b339b419973cf3e788a05bad9fe7d4b62a3707af4dd6b825c41a814edac407b0b48d723bba13d4768da5cbcd4d460bdb66e5596d518a73c6d58df139e93b12e5d00251f531d0bebb754acc343d1ccd6e2baeb650fdc70a6be0f3f198047020eaa1e8b314137af4a2f62bf1a066ce28baddc35bf6edc99a4af9c0db847cbeb0ce6bb86d9af7d5efe25f67829fb865192b2a672e8e7d805b085cf8318480f0308fde8d3309d38d180393fa4d4ec9d9c65ce22505c10bc05d1e2438dddb53aa612b2654e8da0f6370cc72ef50ef7d6b894300866c71481e15c68e351132f5ea53d1925304880fca685ee87c1f022d67d9c77e47aca9c81132742171e305dbec6827143bd1bdc2ef48d43cbd083150a8735ad7d4b954b891036be8b86bdfcd4cbce537924caf91241bcf3a95e0d216b6fe91f5530bbaff55816041fd03d0c691a6ba4984dbd5b5cac64bdd9647b84fc9f413bbc04da159818651d1e22d8cd217ca0f48a18d99f87f0b41816afd28db0c47b2293015d80ea1ea01a48b3936ebec85f8f2eda8961410c5a9a5e7748dba8d309aacb9cfb4a617bf68ee2a2dff5257ca13ac031bd02c0cec99207fc2e603f80c0675ada7694328d4ccb0d464dd83d76a2268fe62ccc95aafc097f146cc67ff210b9f8f14a7886d81be7473b72518455827ba88ff6436ffd2ce389650248cdea178c1fa9014cd3c33082054106092a864886f70d010701a08205320482052e3082052a30820526060b2a864886f70d010c0a0102a08204ee308204ea301c060a2a864886f70d010c0103300e0408e0c25fbab714e22f02020800048204c88e61de00e92f62481711cf50e9845f057d71113358c0ea539f5dd8a6b84138a30454022476ceb5be480732187553fb94898240880b2918c09794fcb8261eddadbb6235fdb4cece8d57d684af8c3b694ad709582c7db46342f3945b697e7779299986e5786a0e081cdaec348ff8425332fa9f16a483ca04b33974815ed270ab79ac3dab3d814512333996ea62c50f15f6f75e2b26a717cebb0999dc76b19b22171d61c5c9f132275bb3f606df0766e57f036ff5eb838730d4595ff7920b2028148ad77eaab5d4c514e5c874e4b8efd662f6ecc17b3e28978194aa71721f41580cfe255b83f04a085b9ece1186ff079038590ae6c672aca977c3f849f43c88101ac62124694d3a9de6326f21694a0fabd64f98e44a3b7b11da1b6aabd403dea603b3de32007d974fe300c15bc7d39d937314958d6cc99890c2e9726fa0050574969e31154301155d83ce929a8f781f60759dc1e9dc7cc108caa537f1673bb5a6c2f39c807e73fa19af0cd030933f943b613f59cd18c907c1e58489f37d4b92dc1e20499614085802f4d408c201a5bd19eec7e8b4c6d640b7b295e656fa3d80ad35b07b4ff828296a4ff87cff5e2300913774ce3f08385ff27841ad6ba0de0899fe7477d05911e47ec9ffa10e7f7a5aea5cd9890f8e790cdb6c7c68174ea878be69baadd95fa9b6c9b516bc1947d38568711c8b879e978028fc02c4a3468823e1aea7964994e416ca6dffa551005c7899f8afdea00d1b18924153eb26ac2d92c0798a97978dae51592aab90537d4d0ed7d72dc82d074d0d765be9b456903d1eacae97c974d59ef9d9b4c90ec2994228e66a4fc8f393a8cb0477811bdc4179e73be8f613c0d4b8e9ee636c623ac82bb348290732482225376b6285f630a74c75dd89355e27af97887fc67e84855560515f914aca493f1032ac147b511c7572c8d1e5452350823b0778431c7d83e173fe6c96b8c8a2bacf7ed37194f14d9e69d8ef9e0c1669fd8d781931ea8966c1eff82baa9b856bf4f48eec8d0e153d6f553d909a730ef7d72bf40af843a7cdaf21e034c8b2ce1563fbc8e59af88ce17c1391fe9dd387cfd558438581b336a78c50e9e28721d9cb7e9822023845648499976bab4486a2c17543977d3527574d8392764041c7167ab38ab994e87831b29d79ff6e4e07e188d187a2b22f3ce002457ec8142e988c69b83fa99a273e4e4f1a976833c2568d00904e9c10bd57da6106cf61fbe98a8bd7115b030cbd2cf44e447271fb9021a8819a7620af7f1e0b35113cd0ffb6e3061b73b82c4c4a5447f3282c571b9bfe2b9d802496c7a0cd2929127634d11c5e15b847c022bfcc693b941a5dcd7f20cad5aff5daf16b68d9f8b70a2e5e37de32cd3dc21352edc11d4056192e0b47fc9f199afa3e4114e77f1352e43ece8227681c4a95a4f43ba7afe7d42fff550c8daca73cfd67608c42772fabd4c418da44c1b282ce29f097e74c9f406f8812b6278e6f782e31c7d6f92d56ddf957b900632e1d76d82e0a426d0400364034b40f13e76bbbffb05f97f995e053b5beaaf94c2751afcbcadff2c9f744ab1574a8d627224adc6205043068773afac77d9386f28be34cf5e4f5b4f573bd2eabae317d29912503b6ccb88037969f508a26ed30a179d1c93f328b575fa54ad408901344ff18521e1c4791ad5ac7a6c3269464daa8108c8ba59b18fc52d81e5315f4b5f00fc822c86f625382963125302306092a864886f70d01091531160414f60526b8d97f1ae083d90c655dcd7e0458947577$2c157943e0cf1b4e3c32792d1a9c79f3357cffb522db8e40542c727e", "password"},
	{"$pfxng$384$48$2048$8$6d9ec1eed08eef7f$308209683082041f06092a864886f70d010706a08204103082040c0201003082040506092a864886f70d010701301c060a2a864886f70d010c0106300e040810d1d87bd25888dd02020800808203d8298c7b7782ea470f554960a13a31719becc0642584f1c782652d36d916542f248d68ee6fed7f4beb47b534303467805745e7a4bbca15b576ea23785e716256ba3fbde3c260d4ff31d847cd2c7c6961727f2ed0eb586f3189897a904d7db1e6887f01139886b88d11020cadfe7eb6a947f03c142a15496a9f2bc4c25bca36b70f5d3692e8426bd435a57ef53beec4e6435dcd4ea10c26513c75e0fc7a0f746eea2c796250456f1ea2dbde549d9402b03e15a10cb1bafc8bd6c6ba36b4f9814c037724e963fdb75fd8ae3d9617f87eeede851d7d3e499ddeb11a8d8d6218727e3fd4c78199e0e16a95f7089080cc35829cd2cba89fb01a6d972b4c26a6c4d63f22bd737446651ce6807aa4240440ead384cd821b95da4ab216d80108a96ef9901d695cbd3b357756f7c537ad7fcc3d0fcbfc2ac76cf4b2737d581bbaa61eb1664d1052fc49be8ef85245940f95e756783d38003719424724b34f5d70a5d715bf644bc751170be5b1bfe8d3babed56793d6cbc92cdd6d2075080bf5adf6f5a93933e8febb44a06536d3eb2b70c7e7da0832e01569cc561ddb5de770571def7c612aae2ac6a1d6ce65e2be2db6e2839ffe328c32f66a004f10deb6ef6700e35c801687ad1a945b218caab08daad7cba68c6fdee3fd9256d4726da83b8287ad30382f8349404dee0dec6cefe8acda3a031a8956ad8e287483731abd877d1f8ce694a3d70a70c095dd974cefaa5a03f65f9df96f9e9aeb49514c82ca2e05d98685391532548c7c3050b2b148d06e6d81265fc3968478636a4912ee7d9d59d03c26c02c2c5583a016412edf511bf6c5258da7ea2d4d11e6405a5685a69aa65c60e9b601e45d38195969886059dd4332b3793dea92087316edcccfb114e02d86cf41261a95f80d11f846ee50598b33ccda243a24b87edf39051e43ba252654117280af5913faea2eae58134180e1b6cf0ece48a705cb4a4cb72c4269c31bc61c73d9251d27eff1690e8db033c6980b46c46a5afd363ff8d03b7b54e7558c0f72e3f004f3069eba6da17eb75490e3b380ed4efa3d30597f2ef235091672fc392fca60b6e957523ec3fcffffdef91420be03f53c95ffa59949ae68bd8c5a16443ff2b4013fcc99cc0629357094ceb40543f954e8c1be0714e08ad006e771d03ddfd74c48848656949434980d4f3478dbd8e6e546de0cb0f7f0bbc1f86fe8579ee32bca3002b0ad854c82d16168d3666e70d38f69e30f40cfca65928a8bfd3ec4d4eeec16e8b308f6cd2bc62e9b9204c6af55e8c746aaf105760d2eef67b6a70a04c4e2a26f9fccb9b99f2aab321c6918eb299d96293b392252b9628d5a8f97b4094f66cceca907b30b88b14b3102454a6c6c10f375dbd07eec1175c99b3082054106092a864886f70d010701a08205320482052e3082052a30820526060b2a864886f70d010c0a0102a08204ee308204ea301c060a2a864886f70d010c0103300e0408727935156b8cb4d602020800048204c847efabdcd5bc09bbfd533f7d4b4e89fdc794cb45bbb4dc3db102fded9a0001e60a6ad4b714a3f465f8e04f86af05fc059691c8d1e48b5cd9cd9b7473e9b441c21ffd7a06c67b2436cf521c011cdd0d8b7f4d00758e30323f5714d9a5398b2a2f68c198d3368aaf08b81897ecf507aa3e2db10de58fbc7364391e10b6cd141e4526827d1e0f833793dd09b4de2da52e8d42edc4c3da263eae310f8c9e3a451a6f6ead0825fc6153d12ab799929a1ed37de14f836176aa0ddb35d955d2951939af99a3bfae8f91aafb242417b6de6a0898935fd3a27fec1ebcd0180eefab2183a891432a8946574273bc04389df75b98962843d8d4daac5053d2755bdfd77f5832dd0aa1f9be0b8846870df70a7c179c316f811e450634c99db8e0c57b4629dbdb23f2051dbaf5c9c48a11d512b836f0ba557f1ed580d848794bf5c2039afed40038f76dba684ee0b55dfbd0378dae28a5ecd722a029f3bc0f21b2319541bb90da406b8b946fca94784cd6a1baba56b2abf5dbb512073933b2b27849663fdcd82f6d912dfbca9021d8cf87491cd08092035b2ee5c44b6aeaaaa798201a9012a558d2cbfb63fb40792bb007e6de2a571b204013665d35896b066597d8c22f11545fe5cd814e53d66328fd083df315871c86fd2ce9ac92fc8c694b207c4318f6135b3ded8e0b25c16214634140afe47fbee2292d1f314a1da987f98e61e892731ed9919774d96dc0d2b0a2db4ab4f2ad6f3c94efb9b206cf5960df283085938fdc953a2372fbe8d5dbcfbad2c552aa0f93fa4a0ebdf76a6237c34dfbe07df0739f1c4c3a2dfaa8093cb9077f42d70c8133824ee3e3945f24898b4c2ad31990acae6a9353279f39ccd9de91d8283fbd2c628e8bd079cb6183225ac72594bf2f33edeacfabf15d210fe321b4dd3cb1adfbeba31dacf4d8c7f10ea240a491ded051e7a992a8bc5f10552787e54ae366c7fb87ea7389f224477837c4e4c93e3c5797ec67aa7d9c999ef3d155ff55846600809986420c738c3af8e221b777b7ff8fb36a5fee9c3dc99c51ea57ce702cddf7cb5ff3b3b8d942a37c2058f3b99333ef312a6636f66cc77e54a80ea9bf05c9df70aef68e93dbe5b34e5d009845a7483c95eb624b0100bcbf04c6a60098f82ab643be533c7e012456cbe7f9b1aa3ab45db4aaff53c80226e53ad5ec4f32ccb08edd858c128c5efc43d53a075ffe10295bdbf39ee91fb95f94374acf603225835e24ae9ba95c6b8a911984cedb1c070d2ad5142e3ad9768f5147afe7f5a5b85f763fed9a093e2c24f920e6307a9e5418293b4777177d813d70dbf2feadb7a49b382dba1371c9887fa895b7fcc2b057aae2d6e40507ed33e368ad0bddc6503781b22023b4c41a9ae8c805a9ef83a33cf34c05d6a84472b2e7efc5c2dab12b59a474d1bdc1c015c0ba61f777946d6e1fda7fc4b2cfbff26fd6f04d9f438483adb1216d86863108e3c1ba17b9354c914d7eaea2a32fe4616d911e09dce3015ba3cceb87d5da150f720075d50897b213883942b1fb3fb206801890e695d1dc33c04f340de718db8e28dc4afcf9ac69456191383b3298db189847afb5a647d5bd5c8b639954b1d261569bede67af7f823172ab7728f714ef4e63f04e4c3596f86c365862cc11d95848725b661a5c943eca98399fe9773c7fb4371fdfe44a202acf252d8ab93a320e11607e89720954ac7bce878adf374bb2e8b975d1a23713125302306092a864886f70d01091531160414f60526b8d97f1ae083d90c655dcd7e0458947577$f9dddb4d707010511ec6e2ef656fe5adf3c24973acd0f7b6d71f1d1aaeb336eb62c6f26798e52fe4a1a743abd035c795", "password"},
	{"$pfxng$1$20$2048$8$7aee6a7d66fe6625$308209683082041f06092a864886f70d010706a08204103082040c0201003082040506092a864886f70d010701301c060a2a864886f70d010c0106300e04084bf94df7d0744c6a02020800808203d8b9624b3516cbbd4dc4de04f1e73ddd6154bdb1e4f9f598461fb55c8959edb1afe9d9f354a0ac7d9394e2eb6efb0e438032bf623fc719ea951e9a40dd66220c5ec41f97a71d5e521e38f75c6c1705dc21e6f6b1e055e2d4ea6baee34a5acf6ab92407237b0a956a23e74e0774235804df0753d50d482e354eedec2d75b6a640282e9b1ea5cbe6005ad0633a0694428bffd9cba0711197cbbffe7ac8006b749738d272f3c22cb61d8d9c635d8f3adf6baa207fd1c1cd864b9f3e226c100c557e55a26d6a836435d8f4cff21133b1102f06e0d447c9b866e1f2f12c40910440a3c523356389b44f41a1e91652105d966e0194c99dec35965f4ac437c66b1ef3913c59036eaf431422199f416a676cbfef80ccd4bf714e5056a71d14d054343c7afff7ecea9c926eed52302516ace0a3fce361084599c86cc7afcd9a0ce31e2ff4fb9b4e9e6db78cdf8c79992014b9c14c234dad608a151a904dd6190a28e8f3fcf3798d50d7139848bf1a20cec45c228aca393f83aebaa26c8c0a606b3922ce6f299b9cecb774c5b96988f4e719e102e6159bf7b2819dcecb47334b6dccfa08d9941e57e4c4985f861c7f7621a9c9eb697641ff7c180f58c489eca1503409026d00a8db9db99149494fcb57d61e107ecb091789541948ef586f57461150ff85b574dc8dd0afe5dc5221aa021dd00c5c42ed4c9769c367f6e6a2a4b3dd55a19514ecf41a24b5ca686f93627c3ab6e931495fb6b1d4d55f9b9e187a3c1ad946102e72ea625d938ac362421f55bbe5cb87426e04afbb45a0ae54901e91c0f2dbc5176bc3799e32638fe1cdc127c85bc2928dcb0c4fe4e1af980235fda918d641a0d357d60584be5a8556009099750e76fb12c0607e3389fa48d72e10b5872cb055452c4f7d60d9782ad5c5cdfcf15157e4511d1cac0dcafdc522996c9103aa074d65fd457c7990c1801381882437c4ba7783622c4f594d97b9138318e04bab564a3e06bcf2d4c12137accc3965e14723e4c255c8fdc7e4784a27eed15d5351486654cadc65a7a9321eb32890be6932c4a0b0ead304e9d9111a909dea06df1dae46d1d60db20cc1026ca75784afb2c1a79a85bc9fe4d18990bbe19147063580b59cbce4e9167c3cab4622d0ccb7463382c734e5aa5a2276250d266db1bd03f85edecb30949e59ea258885c39cd145dad486f4e953ea6f527f8eb11858d7c61f79c62a9113be7c3c3a5f6b9531c76669ed06ec19d7dbe2419856801c11b12386a9fc6b60ce16b2cb13b8bf9273d25ca37f221aaa538d4cd618f0d2c7bb56cce3bb64e3aef0bb6e16003be8f4c6abed5c46a0e89e4fa7628480ceadcc8d771b44d84f9fb4b32b10ee19698707fffebd2c04ea699209e0d7980992fcf63082054106092a864886f70d010701a08205320482052e3082052a30820526060b2a864886f70d010c0a0102a08204ee308204ea301c060a2a864886f70d010c0103300e04087f3670253d7d7ccd02020800048204c80c7bda1e28e835f2d86c751e4543e563855e6583ec291b7f5ec1057cb20fc967384a405f8736db95c10692fb946b617cf08f52221a4c685a77225f3e5b0936303069b898b9c2e0beeec48ac4891107de2d38f9718eecfe9d5853c067c2b5386eb971db1cae925cc0b2bf01acfda8d7105ad8589f86e6829e37b33a59564f582674981992e8a035f62f9d48e963a553ca7ba9c0a1b748dd3a091607476a67e45d29dba9716ea6bcafd4bd5d040b45aed85e7b74b8be43c9b53f30b8d14dd705a302021c6c9831591e50ef01c3733a750caaee661e0bc9aecf9af5da661c0aba99aab5e349a7e0af248048b698d704c04271a0c67d97e482006bedaa7d4b42d5cf486ea34861acd99256bbc638683839d55188391cb720af0ca5065c6ffc10b7d2f9714f7bf391310deefba706a7cc639365c89b927bcc156ae7259665a87000387ff928d7813f43c1af9712ce4c05f646a9f20eae93e172bce2b359ffcff56ab598eda72ca0b9d755f4d5c464768ecc9b450900e0be7b10a5a1efc0bc25ed1450b530c4c3a441f775d1aee25256b8470a8a5748c49a42f97decb083ddb0b595d49d56f61c5fb1da5b0167e7832876e2e374e03553d93f835b23ec3924d22ef15afede70f7b9f1bc0385827814cbaf11a9835eeeb6802769e1fc4bd17b5343015a147d69355bd15f87027fde6629e0bb6c1d81b177a0e753445bb6ae75a9dfd4777ccadf8b9a8c452e3d48e021122b5cc55de6c247d82b3dbbf01c788ecc3524f070969be8c0f9f2600ae51be4939c1604a34332ffca45c722c6d4b67cf160588572ab0637b4a2af48d53fb779267e8f45935992e6d3892ce8d5d07b7d5a7e116c262bede3d04eb99ae3f991f3cccf295fcabc01cdf1d1d3a0d5d7d338433198112b94d620f930872db2cda70b5537d339c988120c0d4a182c1d7547350519c362a5a7f63031ea79098863485912333e2d8e1d6718f9fe71a3080389377e1706d0ee0358ca9f0700d0108a9f345f9ee315f97fe0bffc79668321cc0f955cab9ac060083b46882741e0fc258060fb33de74110ba8a7f180ef65aac011da9d68b9a479b6264462ddeb895d1595378df5b237c07dde2147eb645b12436dcbfe4625c55ff1cb53fd1799b4bfe400ea3fe299ad8b07c92937f388c1432fa164e196524d8dc6e1c51838ae1817cfba18fccd59abe6b6ca36dc1af115033b00035d46b0722da1b13818c525a9d210022e925f73c59d785e48987088e789fe53e22520f3ef3583776f21cd00562527a8e6e6553b8f1bc07ca8fc3bbe721b3261e7448ee5e3e9b5fbf0999609708d8acbf2ddb3e8fc939b523f472af686f096bf43cdf0278db2ddfe5a69bbcf8a179a769978d0e682906e5a8544a6781a354da66355f8cb3ab9d1a5f1ecc19d62ab70e02835b2e103ad8190e5371f147ab5c214d371c2995a5fef9ac841e9e59c29fdfd72648203933cbb4be7794bbade5f22e4d6f4a6cf975545e6448d29be17fad043844a2467b936b0c86fa3ae532d8d050288a10a0597bd7174d3d96127b200f46882cecb64e12c590a37cf1a956680717fd65fbbcf7ca22620d4b7198fdd05e6d089c1ce61e3d85ede4350457e34b541402f6eba9ffba17850296244b5d3661fce38998c244de4b94acdf57ce2339ea15218c4983c493fa5b0a7811c4a3e4f1523d929ec35aa1b0045fcf62788ef1848faa3f08015da2dc1f572e9c002183125302306092a864886f70d01091531160414f60526b8d97f1ae083d90c655dcd7e0458947577$683061aecdc54815e1d34d14f5a55d97cc11418c", "123456789012345678901234567890123456789012345678"},
	{"$pfxng$224$28$2048$8$3f7db8efcc171c50$308209683082041f06092a864886f70d010706a08204103082040c0201003082040506092a864886f70d010701301c060a2a864886f70d010c0106300e040887fe7e5bff5710e402020800808203d88a0d5dd158f1a9a5661bb373a396a380e74285cebc4bb40152ccb22a39ddeac8f977b0383569b292759a766f723b7695494532875ed288747050b8a9a096da8d45f11505e1c9762014ca4ea88d16244f5e02e83330dc377dcf6d9af0b0a1d3789cbe1b1ef042eb38851e055fb79fe57dec96a366274297998fae9276720f62807bd37fe0d49b2c8776c232f6886a4c6508993cd4c267b8534b14e454292dc157ff95d27578a0a6f268fcb88f793039aa8d59a1956e6d4a46b9606cb31f2437b627c6ac925754d65cdcfb6bc9271daa3baecb7af1f32ccbadb0f639c45e767428329c9c60d370f81e3bb06237686f5844aab25cb5f2a451f5d13ea7a767a9b9bd89d9b1052b06ccecbcac8ff68c764a59bfb939bfcd2e21299019070437a2ebf1f69646a2728faeb4f54890219a5945f0079b2af5e93827cf1a8c5ed41cf108ce8fe6375a812c3ec35f3184aee38bd5092b6bd5a2c3094f9019b64295ab46e54d02262aace92287228b0794bcd340069e63107c3592ad411ad4e5dbeb5fea25a2838fe04402992e7141a565b0660211ff5ab69f2e3268ff4ad4c8814f34cc21e572d7a6cb13f86c593f865a7c82cdeb159dc3d84bc5413c235dfe6dd0016f1eb59a9730ed4c4417b2aa3394a26b8fd7852e70d0afb4cfb674a1b050e96dc51df1db0b7f885173e94db928b70724d89586af381c6b6bd30c43023c7700e490515cd799ed7bdd26cfc3c00cfa4162cc0761221848029c336c05208cedec21c194f9641aaf03b34acdf240eb4fd8f125c8803b60c0d82b91553a565efe46013da91bb4437631322ef32dfb07e9021d2fd58a01fb10acf0ebc15866adab5c22174edc58ea7eddcdbcb0b0b5e39cc2f6ebf0cb7c1018ad4704f4b170c47f9db713b8c444826ad686daed3bb4019ff906cebd65cf96fc4840e43c856f9ca45d0cb0528ffaf4f220392c03e0a6c34f4b8ca959d838c3bf059cc877f37c257769bd89d93624112c1e860c5a5ea20f10fb218adacee12d94a8cb3694620fe1eba547971ab0e22f8765b5dedca8ada83c219e5ea3f0d32abb45dc579fd73ded56507eef8edc71a67483daba2427e7761c3307e2ed0c809ccfe3c8619c9ec9e505db58663d1e456d4dda80522e5a4d6f0133430b6fd56856241091ca00920b928cd96c64bb14214a4cc007320f445909e01fd0f1340c64be9118f60fbcafe19a18476806ecae7692e3b527e8fabdd24200727cd2200d6d67606023b9f453ef49f802e9cb4e6820805a60b1ed9ec0df1547e707e22f8466f75cfced0a8a522eee5c6b4f48366fdd7d0ea61addd5e62d23e1aa3b5aa06989064f1ac1a64ebf670a8aa714f76ff86313b37927337dd2ac76d14df7dbc79d2407669a80a4243e3082054106092a864886f70d010701a08205320482052e3082052a30820526060b2a864886f70d010c0a0102a08204ee308204ea301c060a2a864886f70d010c0103300e0408d00ed855d37c4e9d02020800048204c8288d70572c9b06aa500540f5ab37039a280bea3d111236da9115531cb602b8a25ef3c372e5861f5f65e5a5532263d676e5799bd20563cbac0372be86ac49599cc4ba9cc8c7549e1ea3a9a48603644b3bfe73f59c9f801dd3b19a45002685b6414ae7e5fc4df9b39c1a22f539e3b7a7b1298c92cf7e151ffae9f30c818fe2812016deb51a635132c2451749d15a791003585e27a7363246d842c202b5609e509e6bd722c61007f1e0a3f8bd844a16ab1e548f324026a2f3147e9adbccccce45a06fdcb71c6aab442dd6de4bf63cda0134cd485f542baa20db55838271952abf9f06c4742d1751b1fb79633b120e0481276dea9abb408fa8954514fea4ffbc5710a2bff96142bc0b5728b55c38425715e807b92c5c65c1e430d59b93b718436b773a3da1e86075d1869112cf538c33e4751608886d1e895fb0a217c812d0bcbb0c14e30df68e4bea08e49b292ccb59c2de631b9a2c1a8b2969d59513abab17fbcbb300696313c34821b53b79f3afd40ab9a3149ff02fb1c9c365519bf21a06103bcfada7601de0d3c791148ef64a022d22f478fcf8e2ab1d853cc9f2f09bb88cbdec2d9d2dc5243c57c497c98437ef80c81517ce8fb33c00fe4f63c7ba784d247d951af651ff53462af780999230cbdb964a87c1eef716fea6f20aa655980c00da0e438e22c26c534b7ad8c3f62b91664b8d80cb0834232574ab8e1ca8d436e364a0efb9ddd2d77966b108eacdf67619a7e2ce7de0a9bd437bc5adbe769e01784ebca2142481c8ac0f68a0a0cc24aa602a9beda6134b296e3bbb422537fdb00e25649ea4fb55e63f8fdea9154cefc0d51173cc33f9d83ddabad659b0d951fe66dc2f6b59a6723b988b4ac440dcc126e7d73f7cacf754ab2cd0966392b6821442ea188eedbdf9af27009632ac96d4bc8dda11376f37f4d378182b49118a8b11a964823960cc09c388623ea5f44805237abcb990b694d40e9c729372458259b0137b3f838633927f679cdbcda1abdad6f90d0869524246a56931ecad8d4b1fee47d4117dda804cdd7f94c32fd0d7640f63f9137c5f124f543282935db35357607453493ffbee91012b63c81c19f6c732b99b2ea44aa6e74ff881b38fed19f5857b9bedec3cee375f08d080669694c55c14d1c7951fe906ac07c13e316f00e393cd5740b57f22f03a207b87a4563fd37f1b54aa03c9d94e19621fbc1c949fce6a04eb04a1c96a008ed79cde47fe8aef003d6d2dd186e5f85faa0a2b39def245d2f85ea04cb59083f4482ce852f03f3159df7c83e5971b147a66bafec1140f3e4b3ca95ced458dcdfc9fd0b932388dfbe426893d368c62030dca4c81b21e794dcbd4843d372c378942d7514447b1ffccf89d13983b414917463b97ef8b81acf7f3b850ac102cd56622290c85467372a606a2aa5011caf1a1701058aaed75ce6de458bd6bfd38bc5ad09cae2c07f03b598dda595083325e78627646af854b975a5081bfb246489a01d5653d90c5b16ca98f41c3767495ce9eb5038eea4c3863c3b01aa1a53e82eb6705d521fa2ce1948099f3c641f477f29c1bfa0f5f2f32fd2fd5c2e5a28b05e80e6899cb74f1193e5741cc4dc1d2b68294e8490bff93b587ad265fce489f361e0ef3a78708c1fc8f6ba7f14a3839dfc5bc08c328239dbadb4f0cf0637156aa6fd057c006582e9fd437791bbd1d533c443d405956f5bd4ff1fa5b5ab34f2551288c599f863125302306092a864886f70d01091531160414f60526b8d97f1ae083d90c655dcd7e0458947577$d23b2e7bb22b77fac9424b8a7164c559ca9e17d7ad59483d77f65412", "123456789012345678901234567890123456789012345678"},
	{"$pfxng$256$32$2048$8$dbb81801e6cf5ffa$308209683082041f06092a864886f70d010706a08204103082040c0201003082040506092a864886f70d010701301c060a2a864886f70d010c0106300e0408d02d1543dd98807502020800808203d8b216863698fe99b399c476c5647b54f8b8066c95a6422a64f77b3566fde10804ded41663f47a5bfc1877965be9b0713c1e6c9cf4add5ebae35a96682c0c49ba8fe271bb750351f46535ccbd0c3e7a854e9722ba59c7e8a9a74209da359b7ecac92895457ed1ee149dd7c6aa88af18b92ad63ed91769e1760a59c9a81de182192ba642748f7baf5cbd25e909d15d94a60fd5e2cc5676679a0e5dc1dd728c8001bf74c08800c87ee0c7d704775285802483eaab253e0240722bd21244f571a0c998a4234239503daf6b0f33555c8169a54db71d74318c2ed8135e97a7f60fca5e8876cb265db2a4ddcf7180396fd366195fe84f6cb75b292c1c104d3b9f3bfb5d5b17d9c68da934daa4b376a1ef9376f00d33735dadbc8adbcc90f674b0b8342a677f9e99327fc721e4105bc9fe4bc47365e44cc94fe32b5af8e354f204ce579bb24ecda08da219e8a9ddf8924762d57789d7782e06948d6acae25c0875fad8996a8bd7a916313a86854241b5fb600339b24ecfa865d7cb333f460022bad29b8be2869eb006efb68fb501301397ab395b7b2a6e42ab7bac644d24370c40fbb69a4c444b6b2f0abe1cb0f0913a884abd4826a50ab8f352455c71c8621a071028f7b0d1fb144f29cc4faf778c32f2491efcc80832b328352220b9bdb6232617c0d6484fc01b7c68f8e34a1928d88383d1be13294cc6c7c3b1b9b0babf33f00243f50c589a00a9a6ec77edc51450f66423972edf6ddc1f42d970c337d9c33bffcc8bca754df7bc7ac773d88140ad7645d0e34595bcd0f4091355f155f4aaee2e25753eabadcbb7a55ed94c4432baccabe837f4fc446f7ae6e669f25a3e1a3f1e3ea2b9c6f6ee81e33da7c9a73cc31dce52dab7da062e281cd2cc336a858e3760229b2d77f2555f93dce5f222968e5e30ae0dc1be0c7d71d5d31f40c2ea1ef4f1b429d9f33a3d415e2c482b324fdbb012bb4e479cf106e242f85201c6bc7ce1fbc521cb9ab47343e675ffc6b68d01bdfabb90c7b35106653f8753e3080033b4bedec0782f7ec54a51c74e489defd43d13a14fd4555e944f66e17e65f5f206edc68996e6282597618cc12de10b0c101ee6a18bcf81624d06529b203cadd9d41ba0c4d8e3598f7321b81503e2bf22026ba99183fbe4a8e37aa22e7dec1eda76ca6a834133f72441e147de0c878014cffb966044e6f7c1e20e444ea358cedd06a32849e12db583975f0d4bc6f2930da4bab30544a3018042a4876be03d4faddf69841545e9895289d5b38b0bdfad43ff6fbcf9bce989f55a85eaf3fcb99d1cf79d61074bb9fa900733e2193650305b77c1342832da3652ce46f378b9cdad1ddabb9210f0ae399490e01b6ed7c60bfadd2c5c2bd534fac0ee83721c4253082054106092a864886f70d010701a08205320482052e3082052a30820526060b2a864886f70d010c0a0102a08204ee308204ea301c060a2a864886f70d010c0103300e0408740ffaf2a993ffd702020800048204c8730ed3dea5e39287ea1c441026026af0b7971511192405c0a5589ab7fe187dd5428186d039f6beb0b04ec891dd087dfcc7c0b7ac746d7019a95d12af486719ccecbb75ce990fedd592c7456803b7582e4e65bd73a0a9b14bfb61c2b333a9335a15d663f02467cb61878685d4966aaac9069cb2f9ff59e307d09bf687e46778aeef3f2a00d4185ad756390548f68c3f107f0ce8ab13bdaf37c18161cfeb919ece97dab44406a72ae1593b118fbc8652e8f18009b0d508f0afa32e332b781584fe0bbba0a00f059c684af00b62c0a6b37feaac9f903da425ecd3d81336115184aff97a3c12d13fe173ba602793176f9bb241ccf21faa782c3b8c05e4486e73e7d96eaec6eeca4eb92d9c9b0fb02e6f328adffae48a5f1485b7a19917ef88cd8d59730d77e180b30e1ac0d0a286488a1f6c4ecf1ee70c83627bd2ef4023749c30e8c7a0b610d0dd96656d68cfc315e6dc4a2f785d0908ce52bbe5c4adb4e25863f5186e1712304656d1d5a5bf1c0dd6f8e9b110069a46099099ad0e685034638c4c165de239d7a7ed9e9b5325f1bd9036be1ea29f61c33faba9a67d1c81112335d8d67d09341663a9f8a0ff5d4b30be4977b67dbba3c8363f550b5316e124aafe0e1e8c6a18421aa1af559bfc20fd4be1507e1bdb667fc7459450554d53ca7d9f134cbff96dbeeeb6778adade7f60d32d05e1ec2eb69dffca27568d2237ff9ab388d032d1531a461eb017c1245c401422a245655d799621e0fe0f4b7a9f019059f0d9476ceb25001d0fa34ec68e666b8dd49bd81c807685f4f4aed108535c21a8b926626557370ed996ea82d452fffb1f1f4a0a7740dcfa0c20d2f65fbdae0b39f4b3cbdc2b3c2e8b4ebbf03c1bed6e1506b61825ae854abcc196e79f20a06adad239c777715224c7be6b667e343759f41ac9d0e15db35c7a6cfebba1a5f8c3ca87baa8a9f7b3e1e729d4104b41d252242c98d9abf45ca040ca6a683f5a0a129e263507a4af614a3289e7f87d7e2d26ab917ab210540540326e9f4280c51df654dbe6fb4ce4c304ee5fef60afed4e532a051ec3c90c838881a338f6a8f535433a82c4e01d63c55dec0e9ddff46ac4374100a7a57103553c7de7822bda778515a6bfa185c1e6602c3abe485cd9d87a8aabda04619d9623b37bd59da209d71caefaad486ca4ed1759cd2114085054f10f302dbf32008ad6df2d3d39d61d95d0ca4693da7738f5d22f6bbf7789db8e51d7fe9bfcb1b40620537f10e737a5646d61ce5cdab7c389f8b26917afe4bd70b4055b9f383a84c019e1b8e14d089c8003bb129717626e796d7692fed085be0bdc8c52ede08271f52fe369846296892fb6c066c6987d41c89c0a48bbdc9f79604eb1288663ef90fa341c68ba68226a3a038dbda2056437b74ab211c78bef11c6e26171f65b63d931f7b7bb568950e0f74a5a75f00e8821a4f704ec75f37d50155afbf2f8afc6476575ae5bf91e99758a757d0d1f4e5016c1fca114667f79664636a2188ef45ab42b33acbbde837932c3c0835b8e30bbf16ce3bc2c60d7c73472ec19ca9dec9b84721acec2b5e20dc36a0e3d55bab225cb238aac074eedf3b56c3c4613ffb962b4b7e7a66ddb93fb7f7c72f110af40bdf3abf299567d4cfbda4829ab04c6d962df6eef92cd04e43ede0cbadba271652bcf5dd8a682b4782a2b9f222b514fbc2311901af9ef99d526c831c5ff479e5313cc9d21b482d83125302306092a864886f70d01091531160414f60526b8d97f1ae083d90c655dcd7e0458947577$91b12ed2d2621d03a08ff7e914224f8e27852ce491737d1f1e866b30017fdb04", "123456789012345678901234567890123456789012345678"},
	{"$pfxng$384$48$2048$8$70e618ee66882d15$308209683082041f06092a864886f70d010706a08204103082040c0201003082040506092a864886f70d010701301c060a2a864886f70d010c0106300e0408b6e1ed3f5e14435802020800808203d87a3aeb70dae99ba99e6420aa49c88e2f4e395257303a50201a89776e5456effc8ad07cad1314d69983ffd8e2d1009e0fc638721e3210811f1632673ea0e70974c52c398d4d1025c80384d979c9daa25fbcc58d539f09915e59d72683eadae739f81225b70e659b673d79d9c242fe5ca88ae9d7730782f5c2c6eaf81877acb7076722cf4af7a7a189a29498b8065417691484fa622d67076768fed288b211d6ab40bc231696ff7064e769f280ca0c873c56e2bbb28269f5ca040466479a05b8b472790ad352cc57f11045a746915fded11f09bc03697b9b1b8969b616a0e94c7a316850651948e49c9798e54208c44d7943d84ce7b9da3842ee5e42660db3515d07ec906fef365b26e5714f5c2b8be1af2dab09fd43ee3445c573817fb0db5b311da0628c9ecd038e61b1b4c2eaa5623232bcc2ba8ed6b7fcb3f7921bbc03ec22f5d55438e33582b002c9a5c1170fc189c3f2c9fddabd8bcd801cfb675fcfdffac676d74b59afe303180c06de76294b7d5282e73c31769b2516f404461b42d16482d8c9ea9bebfea79cd8519852fe0e17f98ab1b59bd1cf1b7856e423b14bab00921f26b722cc82f8f4cadf310ed96a2196e34d3e31d21564276c6e671e4c3c953e5de6c0ce1d711b34489101b65fcc20c58ab635f89809045d3e3246f16f38af549e483dc43b1ce05b2785442a146db4a4ec20d305f5554eca0967ca1dc0e05f07190e1b27259a39bb21fa8d26f36ecfb3daebcafb66852c3064212813b64984777c7c86d6915f9e5172af479c4dcca085ba3ae71554d2d1ea5398f6746c94dcabf1e2feb916fc02394795c27fea5119932f9b4853ba7e68f7186d75115372b4284515bf42290ad4cd3486188ff55f44cfa92e800d564cdef01e58f532d804cdf4fbba4804099d053dbdee709c4036245a72eadca2e30f974102c0f793797117160f08993241aca7c45a45b70b8eaf0bf765b2d7b2fe357f368aef2e2eeba48c975a2e67b99475c5367e1555aa62447326e8e5fb46240f63f34bc4b7cd1b8b8063cbc855888c0bd7491fe55ae572fb6af2edf0396c9dbed2e2eaefb128432cc22e6b3dae21bc3a398a0b4c4b336e9fec0559463093c48aeb49dd74660b7e6a984cfc595324c39c4241093c57487a9c3c857ca8f402c7108c0cf8b8c7d4d5837c9603a9386b8e8628094e4b56ee64a31f10e216272d92423d141e8c5f0f27396c8f6a1531fc6f1c8af01f02c2292049bc6715058e4d6cdeac9f1fa8f46cef3332cb32c1690ec626c827cd4999946fd8bbcac778670c6ffe4e0bc066c17855c9d58b949837bbd299694d59f636125df796be5a456a417df4d9cc7313b15994ca3a7b05b9bbb35418c205120e6539d4707d48afe80deb5677923082054106092a864886f70d010701a08205320482052e3082052a30820526060b2a864886f70d010c0a0102a08204ee308204ea301c060a2a864886f70d010c0103300e04089ebadbc5dffe962d02020800048204c8ffa140237ce6d43a17a750c8775f75db75fe3daacc29e3711f5296cf58afef8d6f45fdb2606856e0f9401bb245aaf74f8ce09bf14e22eba1420c353a063ec3a36c3db8a82e2af71a00813d8b6e678955205bfe8e67784a8fda7309290efc81a59d905e140367ddf0c7440b3838ac0fb31b7d444a29be4a6158ebc3489cb5c354132c9691e9c293a0135efb3fa214bfea8047f26fa600c3be87ea40c204d3fc44f85a867090d87df9d4ae59c5799976dd5be257076c1078710747e23ceee395511f000a6539c79f88a16372393d721c6eea761fa63dada8f01f5b0bfa77aaa65a2f02f161639b1409fa410601f4f5366418300ecd897dccdd14398555d83c88a8c8e398248ed3cde898e2c24691b664dac91adff95700329ffa4c58f628a470f72a26b4eb33b62b96127f3891926771dbcbabeaace79761769819a81239b1f1b85622eb668e399cd25f9a920827b9cc4f6fc9b8991078012b543fba570d14f4eb0da187b60dce0f6dee8a6cc6cd37fccf4b6d78074412f8a871ae21788178ec5787ff7365d9bba1728b91f42dcb05d7560481d1e433ebf0d0b50829a2960ac253de5e9d42016be3c1365478a51d8b134b9ffec742319bbd5b9e6ed40d4e682862270c35467446fa79a39663fca2b9fe507ae038f6315b423f73d76a2a24950500b68c3cb7d251978cca60bc3f33686893940d6fa5c5a8750252f25964e5c59fb52de6d31cce93e90b44e3ae1ae7421a89514de075177101c37e43567f01c8232aca5a09fd628e3d5a6d5dd5d9a7a273cb55f842fae283ae8e79a94c00f28fdb09dbdeea8246740a5107f2b0a22f5adc2cd42e441d21ddde3218b403f3e3409bd2d90a02477f96195daa06a109da182dc1b8d77fbd200bdb62d86e1858d01905ea38a8790c57977355445ffc380eedbc042fb72726763fe8959ae5031f5b4583cff3baf3829b6edf74a7a235bde69103e5d4e8591e14c5a3524308a0d1f4c832aee8f1b2c1019fad0fcff80d4e73676a26f203fd56a4e5607668896feee7ad74e7e10e2fe699b3b6e9cb119c5ca3c69c352c3fb8644db60fc6abccc44836ccbc161d0a2c750c3ba66695a559c0171cdbf2ca6544ccdf247eadd377ff52b6ef3a375652bd9743929c0d839aff5778dfe485219f294dc85b582feceacf466b2a82e785311db4c24a201be15d107af3a1e2a51d9e72a65f6a13b9e04fffe9c50008c4569fcdc9cc7af9858b138189df64006c8702fc8b1866ddef8dc52654fecc889e95bd465f7a6cf6472a09c9c2b8fc1e7bfcb7a8f480123b6fd3244f647cb9b316fb5a5570bebab4d4565152483798607feb07705fda5c7e54d819743dba0c394a928f7837f859cb7ed58551ab7a2f8e6f1d4e05754aff9f2299c24228005f63aeef34653c72b84ddee78b527411b395c5c0f36dc4595eacd737c38f73208943951da23ff3e9f9a7445322ead5d54307adc7965c209d332a24c34305f17638e29297c1f0b8dcf43bfcaa20d6b7b2e106c2aebdda28a7989aeb5b762947d4491ef6cbafffdc79347183174dbe0eae122a9ff35aa2a8aebd94231ee53d9d6f7907e797efbc9de2048ddefb87448ec783583f38fffb4e0e07eeccf9da2d089540845b371e62288543acf21a98b1372a43a90774269bd6032b0a1447b894ab8e2a589636e79c46fbb982bdbe2953983b35e6b378326cc5c792f7a834e0c400d8f34d31492313a32c83f9a53125302306092a864886f70d01091531160414f60526b8d97f1ae083d90c655dcd7e0458947577$ccae69b9fef6124144ae9f566041fe717bbfa2f167b6712ec84233e6647a205dc1441a996defa8fed31b213ce517919d", "123456789012345678901234567890123456789012345678"},
	{"$pfxng$512$64$2048$8$396f32bb64a2fa5b$308209683082041f06092a864886f70d010706a08204103082040c0201003082040506092a864886f70d010701301c060a2a864886f70d010c0106300e0408e89d3e68fd0b95b002020800808203d83f879631d938c0b6b627606a85aac3395102d8dc33544ca92f1b9d64f9bcafda920018221f1772883080e7c93dea9d1c719dd4d87e6e713573aafbb0d18b9ba326c3b3a9a14a92428cd5993c1e4cd8af3162eaef4117a6a83e464d509e1ac6dd77dc5df1d8fb4523459800fda94a261fccbfdd49fd93f2920e7e5510e111c39d35223afb19bffa39d1148f810c41a1cac93f736d3d62b202426b6dcd06c1649742eba0dae9ee2711af32b1755b6ecf7ed7633b7aa84f34281368bd509e492ea9650ea3c234726184775bf059a5acb51d407d29e09b6c3850771c4565bf5b3a4f91c2132c835249c5f4c1430dd583bcefeafcabf33bcc4b17b1b813fac43841db8bad2c186799c240673be19dcc06abb777d8cd092f96be2bbf61138f7cc86f5f636cbcd6f80e39049a28f8699f79e5e22d24a589cdd8c06aa0596b6fb1ad8744c05ccd4021aa58991bdd7fb3545b93571ab34f07681107c4fe2ecc5b81301987ced0cdd7edb249572ccb3065d58284b15fe93560b48e83c6cb082a6f7ea34ae43e95776920618f6726a8f9faca2d65fb4aca594d0cc11b78b44a5725456ac976d22de3ed81d336cce0b6dd6e944f1cb930a82ab66eda9419472196c99bedd8148c386ca9b692f0154a328939d7fcccd4dc97c6cdf740e6e05c942187eaffa11cce08f25ffab2ba25d48a3a87cf0049e62ca5bc774a11dd6c7bbd713206466f4bc1264b2102e8a82416ed31b121d0ee08d2dd8cea305cce65b9500f116de912e02c553470d02cd026f99ee78606bb577fe586f40321edb6f18858978ff183653fa4cb22e0436f7e2c867522da74f601f782fab519942dc1418101b5961c45752ac6ab2eec516af19fa78ccf4d9e8906b6d4000b8f68ebab77360138fc7315d205693a6adf7cc983a094997053df0ba1e9bcbe39b3996fabfc5e7749d887f504a7bf8be40d7497041a63afb323fb9a118dcbf22bf55f688a110dc7716e54450183855600de72b5974c27d07726f69dca17e7c003bef61e3d3120611966d4b6190688ec81ee99548b302e4b8b82437a53b66eee98da497b1e859dd9d7a02eec5121deb04814fd588c3ce2c0d9f35140951a78b6f4c2507fe27dde55c0e879713729ca5ef4279f7068f4f90063f51afced5a0d47228e8085191fe0af7a7d0b78b0db0697b4024015787199eb314328535520dc99e902e4755794d614d9eb33f51d35889086baec90699fc72827970f1aa27d097525c074da78075c57613f4a25957115b010f2264cb2d6772c1372cb66f6a7298059da4149bd2e314b0fee857e13fcd001f2284c4cdc14648f502480b97ff917e97201f1b15380ec6e27a588136b80b89142f1c19b38aafe1455462b70cc7499bdd3a35e5cbadc3082054106092a864886f70d010701a08205320482052e3082052a30820526060b2a864886f70d010c0a0102a08204ee308204ea301c060a2a864886f70d010c0103300e04081fb645183f2c3f5702020800048204c8ff64eb11712a0e513e8de34f5185c4b896d5ce774776983f670f182454ac3e77012d9520ea751cf81e1020dc8aa81b71b6f1865c105c5937d783c03f924823d858d2dd414f9fe83472b61d727b25e4b82ea1d0bf6be385ca8fc36d0faefadf2fbea9ec05b4ffbbd9f4564175107515d14a573c5b849a60ea421e1b53a5c16b3d9092bbf7eba493f29516d8a92b3dd84fad3a099df006ec81736d438d673f0f8bb97b83b7a0d58e2d2e63bc48ee412e21c589f392c7a52d6cce44c39344b9ab293d6b86f815399c6554aa2712b83f0ee39b0a144c2d64ac29f8e9fd96db4446d8fa144af3ac54367b46bf9ce27c1f36242499006fc91f9a5b840678e754309111aa4af0172449b15c42481ab6c85cf9cddfec885474d81ee559e134c07485ad8db0500de8472379a43179fbcae9c24f8c2602a89199164d0609e5794c467524c49e1b162a23e93e780490ba80e39505766809c4d2ec198557a98b0917a2bec6a5a5640a42a0dac2057b9e1c04a897c0ecef2a145bdab75032f2d73ca2082392aa952770cb877db6092dd52dadd1f741267ef60484804c312d582d23987e6fed733c9f5b7a1473e83bf1f92962ec78ece29a9ff5fd3f078ef0ad8898f4a3718691ac89abe091d5c9f47fd4c67f679d8952fc599be43a7513e8ff372eb0f9fba12045ea3f88bad0c6c535fdcd4fb905e125a7669283f65feeeb736e32ad0c71cbc38bce567188e85aa40f82da2c7bfac5608d60876d4055efcebfade47e281340d15a2d84f5f03e61196f549a8ae454e23ccc95a940ef875b5786b71827b95dbdc158b811cafcf84df33c3dbd38a197c7dd7c1db12cfbd7d564c5beb3337dfeb3e56d5e2151eb082763181ea0d4a383abb6b899859a2292e4dfd07795bcb5951abbf1dcb5125ae26f08ac210fd94ee2ececddf54bc5ec1b1176d19f6a2c4a8ad9d910537ef4149ea34e57bc5beebff2586763156d5df6c1030bd7d72318cadb0e0143462add1e2f7cd2cfe4e9ebf1dba4f3b352772b0b1225a7c8befb18ca93392452ccebe4b98fddfe27e0c7b01ad1730ad845cb8230a041e24a95802d0ef543e742360e2b6d9a26202e59cb4ba5f18e60000252c67074ded0c3bc178609e997ef24fa01abd35d3f0042a0721787ae895d3637641e2da9a2073dd2499e805d785441c248b8a8234655083700bdc58c8fb80b8c271deb4a81eacf331473f060d39bc9178b7dd4e6dbd06ad9a9b06a5c955b144bc40beeee9118fbd6128f7366f72a20a042864187195075ff51a4e56ebbf61cd0f079814b5e58fe854bcff79b1e6179a3838a704455bfe8e0a49cd98efaf0184c43b0b05d8e9c6cc60e1a7567238db973d2105fa690dcedbab2f9e8bfa706c4aa159b8e233e02c03ddfaec39ec9618a5bc1186997d01f82d38c3066e6a55aaee186e87b2cb144d3769ee436320aa54efb7259c6f5647bb31840b22e900e141a896aac5403547ad309e7933ccffbcab050e0bbbc6b7f0ca0829216df0c2792fcd1e6945cea18ee33ea3913593192c1868d3e339bef11c77ccad7c3de22711090d042bc0175cca415ef92de7b8d580afe0bdbc1a381ee337973994d098a51fc38fb175245d18cbb5510fa2d2b565a38dfc1ef0a9c2ab9fd24388b18bf90304f599fe92fd64324bd534a0a7c1c32b2c4f29653e0fb66e665c1f4c1b0dddcc0ad561fb3604e000aeb031dc04d449fe44ed0f4af82c7d191dc3125302306092a864886f70d01091531160414f60526b8d97f1ae083d90c655dcd7e0458947577$84b8b3b5751ba689b87acdded46edad28a580116c4f2689b6da009aaddab237ad542ffc337378cd6b938a1c1d5b60af582681513196ca8d97416d83e4bf18a99", "123456789012345678901234567890123456789012345678"},
	// from CMIYC 2013 contest
	{"$pfxng$1$20$2000$20$1185a6aa96733b746ea9c46c3665383e3d3f6bbe$3082099f3082060806092a864886f70d010701a08205f9048205f5308205f1308205ed060b2a864886f70d010c0a0102a08204fe308204fa301c060a2a864886f70d010c0103300e04082e3f6c77f0ce6a81020207d0048204d89002593d2dedda947a1f735474371b7a1079f5b94a672aa9e72c4e7bac6a8391790dc39b367bb8e788a2b523decb93847ffd1c5b2aae71f3f013df06b4227dc6f6c5105b28a1dd7a6dcc0c3fd656d5e41f450d0287bedd6fcefcee2d9f7c78fa12e52b918d055b50bf9b46a74b91e651162382cecdc2c669c6be12bcaca2d3fe93882a2223bcf1d9211d30af57dd52c9a5fbc9919cbb0781216c4205d5e1c6b5d164cea6e144db030377c1d47e3f1aedb03817fdf8b02a5311228f96f3c55ffda3f08e4f712c6574777c8fffbbf566ff3518ff159c2493b53adc87928724bebd07abbcf5256446f75041af515a4bf4544a4987cf03c19deafe66030e80925639b2bd3bcf56cea087fc6f56cfefd642678580b212a5f73ac3050dd1102f3fbf3327b95310f2c65ea3c5f792e14e5a75ed4876eb3a6f214120af5a57a2246f01b8ab0318ae8c5082d06e0e4d6e3c27f32b84a968a495cceb85cf6eb454f74528b1d4b9e588598fc60d89152a34e885930abe0dafaad2d9cb1b59597d48f525df8562157719f3eeb3d06967c0c0033f4d93aaa5386a568f0b611b5d4234a823a90e614eadf717ced18ff4fccb800969749fd08ccd3f7031e5c95e17113b8ad54ec92d1ac15ce32d09ea146dbc41235555c85573eebfcf2989595e5a0308a1cfa1152abfdd41018fe844771ac5cbd30eaaa1e041886e034d034134dfe2304bbc3c5d739dc6e5a8ca2d9b5ebc4ea27dd79138539b9dd8adc2d253edc359a071883b39d95e03d2b237e57e266ed44ad9f8ca404e3893ede20373e0009aa32125fe608c9832e3728b9a394a461d24bc92750bf5e81f93239793efef8b65c6d6200ec59299554ebf8602a0d63ef777dfd442da189e2e5b1cee22a80ef654e71f56c4ad637b93b7c3ddefaa43da143d84262d9f99bb1a976c0f61e41a9c4c60b8212501fb1bdd5754c1f36e75afc32ca011a7cfaa7f58b2d4d4d1911f530c47fc744c75c3606e1b8e862cabfd1b000a4494df6eaea424b77ef6436edf3d42462d7a1c27a9d9a87ef4dc2c17d98c07229bdc76209cfbd456dad96341807a06abcb2132a444020d9ee83d213e50188e998f5a3339c9be2a401fa67639fb0a9baf48f5ef6092a6540449faa0894c165c54a776cf32a7c0dfa324cd09e76514f938061353cc609a7ef337b4eb6357537d8c4862cc53b4c71ffebd5e9e78aedffa6098e249ba5078b6e113ff24d9cdba5fe5f0a03a376e3a2f2a72caafd92437c2ef2a08564ff4bf2f1f6ae33f55c2732ffff806e4578e51e11d848dfba53e3d13c90b32c6a3fe436c202712e3f770eb89bd4c14fca4b1424f14f8f1b71e46c1c17e97096e4a5b8654b33c5865716e49ffccced21367a3ffea2e98c57398247665da064c3825fbb7fb84eca71bd313fbf3f9144aeb7841dba9c51b3ebc5d6539dafc1e6dee0fb55634e5ca336e8ca952e6f63b98897b1b9855c2f863106133e0892b2f5fdb02822438c6836b3089253f1d86ffabcf4c4e641aac8fb0dcec7fd9f27646b7269a71cd3fa5133d21e84ac0ed733d22378810b7258ec68f60d8c70b55960c61c8b98772b93c848403dd7a26c506c71138b676d2824d7b58ff85d88243f6cc5a5809813390ffcb67e01cc404cc11bf06fb974c81216ffe84af66a9735ef04a39061f0cb92ea9c0aa01dcf8478ccc70bd2c34e741e361de47180e31e1923cbd90856186c80a0ec8f66790e0205c0ea9254633807e412d7606b593773181db301306092a864886f70d0109153106040401000000305706092a864886f70d010914314a1e4800640066006500390065006100390038002d0062006300620062002d0034006400620034002d0038003200360063002d003200360062003100350061003500630036003600390035306b06092b0601040182371101315e1e5c004d006900630072006f0073006f0066007400200045006e00680061006e006300650064002000430072007900700074006f0067007200610070006800690063002000500072006f00760069006400650072002000760031002e00303082038f06092a864886f70d010706a08203803082037c0201003082037506092a864886f70d010701301c060a2a864886f70d010c0106300e04087a1638971f7941bf020207d080820348b9b8f734e0cdd2dbe86ec68a01904743c26bb49361a41248c21a887e424dc7571cd3d3cbd40b76a9215a60cd15c785ea427c9858f0d9c92e0a3909901e24210972f3efe5b8ef8994c47e51fdddcfb9da32e464a1675117fc564fb6c419cb49856530fcd2e82dce60ffa42bd5d8edc3edeef687ad49ac4cd0caf5b7248a77d354427156940f1874712f7bf9cdb823aede82ff144dcd6b8cc37cc14cb8f1b8077a95389115e5acfcaee06e68c5118c4cb7a9dfdf3008c834b6a5ad77a41761ff08db75eb31215ecf43ebdb634186c611a145ed4478bb2e0768c536389c88b737001a28e0348a97447ae8a2c2fe8301ab26a04032f44637395e2fca2f5bd92b77d4dff19d76c36c104a9bf8fffbe610fcaa14b3438ba8016a4baf5b4cd3ff22f400cc7aaccb6aed14431f2310609e57faf34fa827a9bd78264058190d93c3641ed8422c5d65576c6d5d1853e20c9fad3587dd1343659c41330b377218d1c63f48718d2f0e7cfc89100c9bb57b843d5af2a4f98c0d88d612a33a5f0ac4f2de31fe448b0ed820a4b92b5bce49f2bcf45bef8e9ec3b83de002016fbd82a350cba0bb75824ab4d9542fc87043fb57ec2970f9ca813563aa3783f70bc4b327a728094d05d8e4fd85cfcab8342fdcbcc30ba9fc77d3261c869543e1d9259ec9efb30c07a11f96bace1ba76612c70c141d0a2aa823b79fd7af7cf6a4e8f8e407404b3942ea51d90388e26c5a83e62612c597fc3a79d7d778a5963bdb81f41da84f0977b350dc4f065d5c29f11cc1cd053091f212b2477ace4ce7bf07002eb48d08d54da229d63c040ee106753b0b661fb08a013868a0f891eb3624f6204ad30afaaf05686977478040bba6473ba9d166ec8a78c8b7ef2cd23795d3dbc0919f46570b4c1326afb9641663bb85153df34585b3f6e679651e08192c364079d250afbf021789c1dfdb49e01bef9fccbf2e31ab61d1b4626b7274716756a74a76dcd4d1878b36abe52fe2b8ace82ed733b1e5cc44030ffe58bcefdc48e010f489107b888b07b6edcbf559558e11a49310cab84d15aa492ff8774815b47fb0a684201d01a7fcb4058c3545a56e1877b772b547fbb9fb5174e00679dda61601905b3d22eda8baf8dbfdefe14a532ceef05bfc736cc614ff12c789efdc3fa71c8432ad58e3c9ed4585a87be06719a02e79$41e3ecfdb9dc0bc6e36028e47caf444bce1e7ee9", "Sw3at3r!"},
	{NULL}
};

static struct custom_salt {
	int mac_algo;
	int key_length;
	int iteration_count;
	int saltlen;
	unsigned char salt[20];
	int data_length;
	unsigned char data[MAX_DATA_LENGTH];
} *cur_salt;

/* not quite sure why this has to be PTL+2, but if it is not it will only find max_lengh-1 passwords! */
static char (*saved_key)[PLAINTEXT_LENGTH + 2];
static int *saved_len;
static ARCH_WORD_32 (*crypt_out)[BINARY_SIZE / sizeof(ARCH_WORD_32)];

static void init(struct fmt_main *self)
{
#ifdef _OPENMP
	static int omp_t = 1;
	omp_t = omp_get_max_threads();
	self->params.min_keys_per_crypt *= omp_t;
	omp_t *= OMP_SCALE;
	self->params.max_keys_per_crypt *= omp_t;
#endif
	saved_key = mem_calloc(self->params.max_keys_per_crypt,
			sizeof(*saved_key));
	saved_len = mem_calloc(self->params.max_keys_per_crypt,
			sizeof(*saved_len));
	crypt_out = mem_calloc(self->params.max_keys_per_crypt,
			sizeof(*crypt_out));
}

static void done(void)
{
	MEM_FREE(crypt_out);
	MEM_FREE(saved_len);
	MEM_FREE(saved_key);
}

static int valid(char *ciphertext, struct fmt_main *self)
{
	char *p = ciphertext, *ctcopy, *keeptr, *p2;
	int mac_algo, saltlen, hashhex, extra;

	if (strncasecmp(ciphertext, FORMAT_TAG, FORMAT_TAG_LENGTH))
		return 0;
	ctcopy = strdup(ciphertext);
	keeptr = ctcopy;
	ctcopy += FORMAT_TAG_LENGTH;
	if ((p = strtokm(ctcopy, "$")) == NULL) // mac_algo
		goto bail;
	if (!isdec(p))
		goto bail;
	mac_algo = atoi(p);
	//if (mac_algo == 0)
	//	hashhex = 40;	// for sha0  (Note, not handled by ans1crypt.py)
	if (mac_algo == 1)	 // 1 -> SHA1, 256 -> SHA256
		hashhex = 40;		// hashhex is length of hex string of hash.
//	else if (mac_algo == 2)	// mdc2  (Note, not handled by ans1crypt.py)
//		hashhex = 32;
//	else if (mac_algo == 4)	// md4  (Note, not handled by ans1crypt.py)
//		hashhex = 32;
//	else if (mac_algo == 5)	//md5  (Note, not handled by ans1crypt.py)
//		hashhex = 32;
//	else if (mac_algo == 160)	//ripemd160  (Note, not handled by ans1crypt.py)
//		hashhex = 40;
	else if (mac_algo == 224)
		hashhex = 56;
	else if (mac_algo == 256)
		hashhex = 64;
	else if (mac_algo == 384)
		hashhex = 96;
	else if (mac_algo == 512)
		hashhex = 128;
	else
		goto bail;
	if ((p = strtokm(NULL, "$")) == NULL) // key_length
		goto bail;
	if (!isdec(p))
		goto bail;
	if (atoi(p) != (hashhex>>1))
		goto bail;
	if ((p = strtokm(NULL, "$")) == NULL) // iteration_count
		goto bail;
	if (!isdec(p))
		goto bail;
	if ((p = strtokm(NULL, "$")) == NULL) // saltlen
		goto bail;
	if (!isdec(p))
		goto bail;
	saltlen = atoi(p);
	if (saltlen > 20)
		goto bail;
	if ((p = strtokm(NULL, "$")) == NULL) // salt
		goto bail;
	if (hexlenl(p, &extra) > saltlen * 2 || extra)
		goto bail;
	if (!ishexlc(p))
		goto bail;
	if ((p = strtokm(NULL, "$")) == NULL) // data
		goto bail;
	if (hexlenl(p, &extra) > MAX_DATA_LENGTH * 2 || extra)
		goto bail;
	if (!ishexlc(p))
		goto bail;
	if ((p = strtokm(NULL, "$")) == NULL) // stored_hmac (not stored in salt)
		goto bail;
	if (hexlenl(p, &extra) != hashhex || extra)
		goto bail;

	p2 = strrchr(ciphertext, '$');
	if (!p2)
		goto bail;
	++p2;
	if (strcmp(p, p2))
		goto bail;

	MEM_FREE(keeptr);
	return 1;

bail:
	MEM_FREE(keeptr);
	return 0;
}

static void *get_salt(char *ciphertext)
{
	static struct custom_salt cs;
	int i;
	char *p = ciphertext, *ctcopy, *keeptr;
	memset(&cs, 0, sizeof(cs));

	ctcopy = strdup(ciphertext);
	keeptr = ctcopy;
	ctcopy += FORMAT_TAG_LENGTH;
	p = strtokm(ctcopy, "$");
	cs.mac_algo = atoi(p);
	p = strtokm(NULL, "$");
	cs.key_length = atoi(p);
	p = strtokm(NULL, "$");
	cs.iteration_count = atoi(p);
	p = strtokm(NULL, "$");
	cs.saltlen = atoi(p);
	p = strtokm(NULL, "$");
	for(i = 0; i < cs.saltlen; i++)
		cs.salt[i] = (atoi16[ARCH_INDEX(p[2*i])] << 4) | atoi16[ARCH_INDEX(p[2*i+1])];
	p = strtokm(NULL, "$");
	cs.data_length = hexlenl(p, 0) / 2;
	for(i = 0; i < cs.data_length; i++)
		cs.data[i] = (atoi16[ARCH_INDEX(p[2*i])] << 4) | atoi16[ARCH_INDEX(p[2*i+1])];
	p = strtokm(NULL, "$");

	MEM_FREE(keeptr);

	return (void *)&cs;
}

// we only grab first 20 bytes of the hash, but that is 'good enough'.
// it makes a lot of other coding more simple.
static void *get_binary(char *ciphertext)
{
	static union {
		unsigned char c[BINARY_SIZE];
		ARCH_WORD dummy;
	} buf;
	unsigned char *out = buf.c;
	int i;
	char *p;

	p = strrchr(ciphertext, '$') + 1;
	for (i = 0; i < BINARY_SIZE && *p; i++) {
		out[i] =
			(atoi16[ARCH_INDEX(*p)] << 4) |
			atoi16[ARCH_INDEX(p[1])];
		p += 2;
	}

	return out;
}

static void set_salt(void *salt)
{
	cur_salt = (struct custom_salt *)salt;
}

static int crypt_all(int *pcount, struct db_salt *salt)
{
	int index;
	const int count = *pcount;
	int inc = 1;

#if defined(SIMD_COEF_32)
	if (cur_salt->mac_algo == 1)
		inc = SSE_GROUP_SZ_SHA1;
	else if (cur_salt->mac_algo == 256 || cur_salt->mac_algo == 224)
		inc = SSE_GROUP_SZ_SHA256;
#if defined(SIMD_COEF_64)
	else if (cur_salt->mac_algo == 512 || cur_salt->mac_algo == 384)
		inc = SSE_GROUP_SZ_SHA512;
#endif
#endif

#ifdef _OPENMP
#pragma omp parallel for
#endif
	for (index = 0; index < count; index += inc)
	{
#if !defined(SIMD_COEF_32)

		if (cur_salt->mac_algo == 1) {
			unsigned char mackey[20];
			int mackeylen = cur_salt->key_length;

			pkcs12_pbe_derive_key(cur_salt->mac_algo, cur_salt->iteration_count,
					MBEDTLS_PKCS12_DERIVE_MAC_KEY,
					(unsigned char*)saved_key[index],
					saved_len[index], cur_salt->salt,
					cur_salt->saltlen, mackey, mackeylen);

			hmac_sha1(mackey, mackeylen, cur_salt->data,
					cur_salt->data_length,
					(unsigned char*)crypt_out[index],
					BINARY_SIZE);
		} else if (cur_salt->mac_algo == 256) {
			unsigned char mackey[32];
			int mackeylen = cur_salt->key_length;
			pkcs12_pbe_derive_key(cur_salt->mac_algo, cur_salt->iteration_count,
					MBEDTLS_PKCS12_DERIVE_MAC_KEY,
					(unsigned char*)saved_key[index],
					saved_len[index], cur_salt->salt,
					cur_salt->saltlen, mackey, mackeylen);

			hmac_sha256(mackey, mackeylen, cur_salt->data,
					cur_salt->data_length,
					(unsigned char*)crypt_out[index],
					BINARY_SIZE);
		} else if (cur_salt->mac_algo == 512) {
			unsigned char mackey[64];
			int mackeylen = cur_salt->key_length;
			pkcs12_pbe_derive_key(cur_salt->mac_algo, cur_salt->iteration_count,
					MBEDTLS_PKCS12_DERIVE_MAC_KEY,
					(unsigned char*)saved_key[index],
					saved_len[index], cur_salt->salt,
					cur_salt->saltlen, mackey, mackeylen);

			hmac_sha512(mackey, mackeylen, cur_salt->data,
					cur_salt->data_length,
					(unsigned char*)crypt_out[index],
					BINARY_SIZE);
		} else if (cur_salt->mac_algo == 224) {
			unsigned char mackey[32];
			int mackeylen = cur_salt->key_length;
			pkcs12_pbe_derive_key(cur_salt->mac_algo, cur_salt->iteration_count,
					MBEDTLS_PKCS12_DERIVE_MAC_KEY,
					(unsigned char*)saved_key[index],
					saved_len[index], cur_salt->salt,
					cur_salt->saltlen, mackey, mackeylen);

			hmac_sha224(mackey, mackeylen, cur_salt->data,
					cur_salt->data_length,
					(unsigned char*)crypt_out[index],
					BINARY_SIZE);
		} else if (cur_salt->mac_algo == 384) {
			unsigned char mackey[64];
			int mackeylen = cur_salt->key_length;
			pkcs12_pbe_derive_key(cur_salt->mac_algo, cur_salt->iteration_count,
					MBEDTLS_PKCS12_DERIVE_MAC_KEY,
					(unsigned char*)saved_key[index],
					saved_len[index], cur_salt->salt,
					cur_salt->saltlen, mackey, mackeylen);

			hmac_sha384(mackey, mackeylen, cur_salt->data,
					cur_salt->data_length,
					(unsigned char*)crypt_out[index],
					BINARY_SIZE);
		}

#else
		if (cur_salt->mac_algo == 1) {
			unsigned char *mackey[SSE_GROUP_SZ_SHA1], real_keys[SSE_GROUP_SZ_SHA1][20];
			const unsigned char *keys[SSE_GROUP_SZ_SHA1];
			int mackeylen = cur_salt->key_length, j;
			size_t lens[SSE_GROUP_SZ_SHA1];

			for (j = 0; j < SSE_GROUP_SZ_SHA1; ++j) {
				mackey[j] = real_keys[j];
				lens[j] = saved_len[index+j];
				keys[j] = (const unsigned char*)(saved_key[index+j]);
			}
			pkcs12_pbe_derive_key_simd(cur_salt->mac_algo, cur_salt->iteration_count,
					MBEDTLS_PKCS12_DERIVE_MAC_KEY, keys,
					lens, cur_salt->salt,
					cur_salt->saltlen, mackey, mackeylen);

			for (j = 0; j < SSE_GROUP_SZ_SHA1; ++j) {
				hmac_sha1(mackey[j], mackeylen, cur_salt->data,
						cur_salt->data_length,
						(unsigned char*)crypt_out[index+j],
						BINARY_SIZE);
			}
		} else if (cur_salt->mac_algo == 256) {
			unsigned char *mackey[SSE_GROUP_SZ_SHA256], real_keys[SSE_GROUP_SZ_SHA256][32];
			const unsigned char *keys[SSE_GROUP_SZ_SHA256];
			int mackeylen = cur_salt->key_length, j;
			size_t lens[SSE_GROUP_SZ_SHA256];

			for (j = 0; j < SSE_GROUP_SZ_SHA256; ++j) {
				mackey[j] = real_keys[j];
				lens[j] = saved_len[index+j];
				keys[j] = (const unsigned char*)(saved_key[index+j]);
			}
			pkcs12_pbe_derive_key_simd(cur_salt->mac_algo, cur_salt->iteration_count,
					MBEDTLS_PKCS12_DERIVE_MAC_KEY, keys,
					lens, cur_salt->salt,
					cur_salt->saltlen, mackey, mackeylen);

			for (j = 0; j < SSE_GROUP_SZ_SHA256; ++j) {
				hmac_sha256(mackey[j], mackeylen, cur_salt->data,
						cur_salt->data_length,
						(unsigned char*)crypt_out[index+j],
						BINARY_SIZE);
			}
		} else if (cur_salt->mac_algo == 512) {
#if defined(SIMD_COEF_64)
			unsigned char *mackey[SSE_GROUP_SZ_SHA512], real_keys[SSE_GROUP_SZ_SHA512][64];
			const unsigned char *keys[SSE_GROUP_SZ_SHA512];
			int mackeylen = cur_salt->key_length, j;
			size_t lens[SSE_GROUP_SZ_SHA512];

			for (j = 0; j < SSE_GROUP_SZ_SHA512; ++j) {
				mackey[j] = real_keys[j];
				lens[j] = saved_len[index+j];
				keys[j] = (const unsigned char*)(saved_key[index+j]);
			}
			pkcs12_pbe_derive_key_simd(cur_salt->mac_algo, cur_salt->iteration_count,
					MBEDTLS_PKCS12_DERIVE_MAC_KEY, keys,
					lens, cur_salt->salt,
					cur_salt->saltlen, mackey, mackeylen);

			for (j = 0; j < SSE_GROUP_SZ_SHA512; ++j) {
				hmac_sha512(mackey[j], mackeylen, cur_salt->data,
						cur_salt->data_length,
						(unsigned char*)crypt_out[index+j],
						BINARY_SIZE);
			}
#else
			int j;

			for (j = 0; j < inc; ++j) {
				unsigned char mackey[64];
				int mackeylen = cur_salt->key_length;
				pkcs12_pbe_derive_key(512, cur_salt->iteration_count,
						MBEDTLS_PKCS12_DERIVE_MAC_KEY,
						(unsigned char*)saved_key[index+j],
						saved_len[index+j], cur_salt->salt,
						cur_salt->saltlen, mackey, mackeylen);

				hmac_sha512(mackey, mackeylen, cur_salt->data,
						cur_salt->data_length,
						(unsigned char*)crypt_out[index+j],
						BINARY_SIZE);
			}
#endif
		} else if (cur_salt->mac_algo == 224) {
			int j;

			for (j = 0; j < inc; ++j) {
				unsigned char mackey[32];
				int mackeylen = cur_salt->key_length;
				pkcs12_pbe_derive_key(cur_salt->mac_algo, cur_salt->iteration_count,
						MBEDTLS_PKCS12_DERIVE_MAC_KEY,
						(unsigned char*)saved_key[index+j],
						saved_len[index+j], cur_salt->salt,
						cur_salt->saltlen, mackey, mackeylen);

				hmac_sha224(mackey, mackeylen, cur_salt->data,
						cur_salt->data_length,
						(unsigned char*)crypt_out[index+j],
						BINARY_SIZE);
			}
		} else if (cur_salt->mac_algo == 384) {
			int j;

			for (j = 0; j < inc; ++j) {
				unsigned char mackey[64];
				int mackeylen = cur_salt->key_length;
				pkcs12_pbe_derive_key(cur_salt->mac_algo, cur_salt->iteration_count,
						MBEDTLS_PKCS12_DERIVE_MAC_KEY,
						(unsigned char*)saved_key[index+j],
						saved_len[index+j], cur_salt->salt,
						cur_salt->saltlen, mackey, mackeylen);

				hmac_sha384(mackey, mackeylen, cur_salt->data,
						cur_salt->data_length,
						(unsigned char*)crypt_out[index+j],
						BINARY_SIZE);
			}
		}
#endif
	}

	return count;
}

static int cmp_all(void *binary, int count)
{
	int index = 0;
#if defined(_OPENMP) || MAX_KEYS_PER_CRYPT > 1
	for (; index < count; index++)
#endif
		if (!memcmp(binary, crypt_out[index], ARCH_SIZE))
			return 1;
	return 0;
}

static int cmp_one(void *binary, int index)
{
	return !memcmp(binary, crypt_out[index], BINARY_SIZE);
}

static int cmp_exact(char *source, int index)
{
	return 1;
}

static void set_key(char *key, int index)
{
	saved_len[index] =
		strnzcpyn(saved_key[index], key, sizeof(saved_key[index]));
}

static char *get_key(int index)
{
	return saved_key[index];
}

/* report iteration count as tunable cost value */
static unsigned int get_mac_type(void *salt)
{
	struct custom_salt *my_salt;

	my_salt = salt;
	return (unsigned int) my_salt->mac_algo;
}


struct fmt_main fmt_pfx_ng = {
	{
		FORMAT_LABEL,
		FORMAT_NAME,
		ALGORITHM_NAME,
		BENCHMARK_COMMENT,
		BENCHMARK_LENGTH,
		0,
		PLAINTEXT_LENGTH,
		BINARY_SIZE,
		BINARY_ALIGN,
		SALT_SIZE,
		SALT_ALIGN,
		MIN_KEYS_PER_CRYPT,
		MAX_KEYS_PER_CRYPT,
		FMT_CASE | FMT_8_BIT | FMT_OMP,
		{
			"mac-type",
		},
		{ FORMAT_TAG },
		tests
	}, {
		init,
		done,
		fmt_default_reset,
		fmt_default_prepare,
		valid,
		fmt_default_split,
		get_binary,
		get_salt,
		{
			get_mac_type,
		},
		fmt_default_source,
		{
			fmt_default_binary_hash /* Not usable with $SOURCE_HASH$ */
		},
		fmt_default_salt_hash,
		NULL,
		set_salt,
		set_key,
		get_key,
		fmt_default_clear_keys,
		crypt_all,
		{
			fmt_default_get_hash /* Not usable with $SOURCE_HASH$ */
		},
		cmp_all,
		cmp_one,
		cmp_exact
	}
};

#endif /* plugin stanza */
